添加标签和路径到图表D3

时间:2014-06-30 11:44:45

标签: javascript csv d3.js

我希望你能提供帮助。我正在构建一个带有D3的条形图,我需要添加标签以及附加显示趋势和目标的路径。我为路径添加了一行但似乎没有生成。带有数据的我的CSV文件结构如下:

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

代码如下:

<!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>

理论上,我可以使用相同的代码来创建条形图的折线图吗?我尝试创建一个小提琴但我的CSV无法添加。尽管如此:http://jsfiddle.net/siyafrica/bfVHU/

1 个答案:

答案 0 :(得分:0)

也许这会有所帮助:

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

我必须进行一系列更改才能使其正常工作,但基本上很难让rangeBands方法使用条形图使用时间数据。关于这个主题写了很多东西,这里有一个很好的(简短的)convo:https://groups.google.com/forum/#!topic/d3-js/7GsDmnB4kdE

我将其切换为使用日期刻度,这通常会起作用,但您必须做一些工作才能使条宽和定位正确。

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

此外,您的线路生成器需要传递数据数组...

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");

如果你想坚持使用序数x刻度并使用范围带,你可能需要一个辅助时间刻度来绘制路径,你需要在域的范围内添加所有日期,否则“空”天将会没有出现在你的图表上。