简体   繁体   English

向图表D3添加标签和路径

[英]Adding a label and path to a chart D3

I hope you can help. 希望您能提供帮助。 I am building a bar chart with D3 that I need to add labels to as well as append a path to show trends and goals. 我正在用D3构建条形图,我需要添加标签以及附加一条路径来显示趋势和目标。 I added a line for the path but it doesn't seem to be generating. 我为该路径添加了一行,但似乎没有生成。 My CSV file with the data is structured like so: 我的CSV文件的数据结构如下:

date,projectCode,numberOfSchools,newSchools
2011-12-1,"PRJ2.1",1188,0

And code is below: 代码如下:

<!Doctype  html>
    <html>
        <head>
            <title>D3 bar and line chart for Aphellion</title>
            <meta charset="utf-8">
            <script type="text/javascript" src="js/d3.v3.js"></script>
            <!-- <script type="text/javascript" src"//cdnjs.cloudflare.com/ajax/libs/d3/3.4.8/d3.min.js"></script> -->
            <style type="text/css">
                /* the style for the page and charts goes here */
                .axis {
                    font: 10px sans-serif;
                }

                .axis path
                .axis line {
                    fill: none;
                    stroke: #000;
                    shape-rendering: crispEdges;

                }

                .rect:hover {
                fill: orange;
            }

            #tooltip {
                background-color: white;
                -webkit-border-radius: 10px;
                -moz-border-radius: 10px;
                border-radius: 10px;
                -webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
                -moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
                box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
                pointer-events: none;
            }

            #tooltip.hidden {
                display: none;
            }

            #tooltip p {
                margin: 0;
                font-family: sans-serif;
                font-size: 16px;
                line-height: 20px;
            }
            </style>

        </head>
        <body>
            <div id="lineChart"></div>

            <script type="text/javascript">
            "Use strict"

                //The script for the bar chart and line charts goes here
                var margin = {top: 20, right: 20, bottom: 70, left: 40},
                    width = 600 - margin.left - margin.right,
                    height = 300 - margin.top - margin.bottom
                    barPadding = 3;

                //parse the date / time
                var parseDate = d3.time.format("%Y-%m-%d").parse;

                //set up the scales
                var x = d3.scale.ordinal().rangeRoundBands([0, width], .05);

                var y = d3.scale.linear().range([height, 0]); 

                //set up the axis
                var xAxis = d3.svg.axis()
                            .scale(x)
                            .orient("bottom")
                            .tickFormat(d3.time.format("%Y-%m"));

                var yAxis = d3.svg.axis()
                            .scale(y)
                            .orient("left")
                            .ticks(5);

                var svg = d3.select("body").append("svg")
                                .attr("class", "barChart")
                                .attr("width", width + margin.left + margin.right)
                                .attr("height", height + margin.top + margin.bottom)
                            .append("g")
                                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                d3.csv("Data/data.csv", function(error, data) {
                        data.forEach(function(d) {
                            d.date = parseDate(d.date.toString());
                            d.numberOfSchools = +d.numberOfSchools;
                        });

                        x.domain(data.map(function(d) {return d.date;}));
                        y.domain([0, d3.max(data, function(d) {return d.numberOfSchools;})]);


                        svg.append("g")
                            .attr("class", "x axis")
                            .attr("transform", "translate(0," + height + ")")
                            .call(xAxis)
                        .selectAll("text")
                            .style("text-anchor", "end")
                            .attr("dx", "-.8em")
                            .attr("dy", "-.55em")
                            .attr("transform", "rotate(-90)");

                        svg.append("g")
                            .attr("class", "y axis")
                            .call(yAxis)
                        .append("text")
                            .attr("transform", "rotate(-90)")
                            .attr("y", 6)
                            .attr("dy", ".71em")
                            .style("text-anchor", "end")
                            .text("Schools");

                        svg.selectAll("bar")
                            .data(data)
                            .enter()
                            .append("rect")
                            .style("fill", function(d) {
                                if(d.numberOfSchools < 1200) {
                                    return "#ff0000";
                                } else if (d.numberOfSchools === 2000) {
                                    return "#33cc33";
                                } else {return "steelblue";}
                            })
                            .attr("class", "rect")
                            .attr("x", function(d) {return x(d.date);})
                            .attr("width", x.rangeBand() - barPadding)
                            .attr("y", function(d) {return y(d.numberOfSchools);})
                            .attr("height", function(d) {return height - y(d.numberOfSchools);})
                            .on("mouseover", function(d) {

                            //Get this bar's x/y values, then augment for the tooltip
                            var xPosition = parseFloat(d3.select(this).attr("x")) + x.rangeBand() / 2;
                            var yPosition = parseFloat(d3.select(this).attr("y")) + 14;

                            //Create the tooltip label
                            svg.append("text")
                                .attr("id", "tooltip")
                                .attr("x", xPosition)
                                .attr("y", yPosition)
                                .attr("text-anchor", "middle")
                                .attr("font-family", "sans-serif")
                                .attr("font-size", "11px")
                                .attr("font-weight", "bold")
                                .attr("fill", "black")
                                .text(d.numberOfSchools + " current schools.");

                                })
                            .on("mouseout", function() {

                            //Remove the tooltip
                            d3.select("#tooltip").remove();

                            });

                            svg.selectAll("text")
                                .data(data)
                                .enter()
                                .append("text")
                                .text(function(d) {
                                    return d.numberOfSchools;
                                })
                                .attr("x", function(d) {return x(d.date);})
                                .attr("y", function(d) {return y(d.numberOfSchools);});
             })


                //add a path to interpolate through the bars
                var line = d3.svg.line()
                            .x(function(d) {return x(d.date)})
                            .y(function(d) {return y(d.numberOfSchools)});

                //add the path
                /*d3.select("svg")
                    .append("path")
                        .attr("d", line(data.numberOfSchools))
                        .attr("class", "numberOfSchools");
                });*/



                    console.log("This code works");


            </script>
        </body>


    </html>

Also theoretically can I use the same code to create a line chart with the bars? 从理论上讲,我也可以使用相同的代码来创建带有条形图的折线图吗? I tried creating a fiddle but my CSV can't be added. 我尝试创建小提琴,但无法添加CSV。 Here it is though: http://jsfiddle.net/siyafrica/bfVHU/ 不过这里是: http : //jsfiddle.net/siyafrica/bfVHU/

Maybe this will help: 也许这会有所帮助:

jsFiddle: http://jsfiddle.net/reblace/bfVHU/7/ jsFiddle: http : //jsfiddle.net/reblace/bfVHU/7/

I had to make a bunch of changes to get it working, but basically it's hard to get the rangeBands method working with bar charts using time data. 我必须进行大量更改才能使其正常运行,但基本上很难使rangeBands方法与使用时间数据的条形图一起使用。 There's a bunch of stuff written on this subject, here's a good (brief) convo about it: https://groups.google.com/forum/#!topic/d3-js/7GsDmnB4kdE 关于这个主题有很多东西,这是一个很好的(简短的)概念: https ://groups.google.com/forum/#! topic/ d3-js/7GsDmnB4kdE

I switched it to use a date scale, which will generally work, but you'll have to do some work to get the bar widths and positioning to be correct. 我将其切换为使用日期刻度,该刻度通常可以使用,但是您必须做一些工作才能使条形宽度和位置正确。

var x = d3.time.scale().range([0, width]);
x.domain(d3.extent(data, function(d) { return d.date; }));

Also, your line generator needs to be passed the data array... 同样,您的行生成器需要传递数据数组...

var line = d3.svg.line()
    .x(function(d) {return x(d.date)})
    .y(function(d) {return y(d.value)});

//add the path
svg.append("path")
    .attr("d", line(data))
    .attr("class", "numberOfSchools");

If you want to stick with the ordinal x scale and use rangebands, you may need a secondary time scale for drawing the path and you will want to add all the dates in the extent of the domain, otherwise "empty" days will not show up on your chart. 如果要坚持按序的x比例尺并使用范围带,则可能需要一个辅助时间比例尺来绘制路径,并且要在域范围内添加所有日期,否则“空”天将不会显示在您的图表上。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM