D3.js - 缩放/变换多行

时间:2017-02-14 16:00:55

标签: d3.js

我正在努力解决这个问题,我正在尝试缩放我的图表,特别是我动态绘制的线条。 在这里,我的小提琴:https://jsfiddle.net/w3j89Lf3/

    

<link href="http://getbootstrap.com/examples/justified-nav/justified-nav.css" rel="stylesheet">
<style>
    .axis path {
        fill: none;
        stroke: #777;
        shape-rendering: crispEdges;
    }
    .axis text {
        font-family: Lato;
        font-size: 13px;
    }
    .legend {
        font-size: 14px;
        font-weight: bold;
    }
    .grid .tick {
        stroke: lightgrey;
        opacity: 0.7;
    }
    .grid path {
          stroke-width: 0;
    }
</style>

我的代码适用于x和y轴,但不适用于我的线条,因为您可以在我的“缩放”功能中看到。

<div class="container">

    <div class="jumbotron">

        <svg id="visualisation" width="1000" height="500"></svg>
        <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
        <script>
            function InitChart() {
                var data = [{
                                "Client": "ABC",
                                "sale": "202",
                                "year": "2000"
                            }, {
                                "Client": "ABC",
                                "sale": "215",
                                "year": "2002"
                            }, {
                                "Client": "ABC",
                                "sale": "179",
                                "year": "2004"
                            }, {
                                "Client": "ABC",
                                "sale": "199",
                                "year": "2006"
                            }, {
                                "Client": "ABC",
                                "sale": "134",
                                "year": "2008"
                            }, {
                                "Client": "ABC",
                                "sale": "176",
                                "year": "2010"
                            }, {
                                "Client": "XYZ",
                                "sale": "100",
                                "year": "2000"
                            }, {
                                "Client": "XYZ",
                                "sale": "215",
                                "year": "2002"
                            }, {
                                "Client": "XYZ",
                                "sale": "179",
                                "year": "2004"
                            }, {
                                "Client": "XYZ",
                                "sale": "199",
                                "year": "2006"
                            }, {
                                "Client": "XYZ",
                                "sale": "134",
                                "year": "2008"
                            }, {
                                "Client": "XYZ",
                                "sale": "176",
                                "year": "2013"
                            }];

                var dataGroup = d3.nest()
                    .key(function(d) {
                        return d.Client;
                    })
                    .entries(data);

                var vis = d3.select("#visualisation"),
                    WIDTH = 1000,
                    HEIGHT = 500,
                    MARGINS = {
                        top: 50,
                        right: 20,
                        bottom: 50,
                        left: 50
                    };

                //Aggiungi ASSI con scala
                    xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(data, function(d) {
                                return d.year;
                            }), d3.max(data, function(d) {
                                return d.year;
                            })]),

                    yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(data, function(d) {
                                return d.sale;
                            }), d3.max(data, function(d) {
                                return d.sale;
                            })]),

                    xAxis = d3.svg.axis()
                    .scale(xScale),

                    yAxis = d3.svg.axis()
                    .scale(yScale)
                    .orient("left");

                vis.append("svg:g")
                    .attr("class", "x axis")
                    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
                    .call(xAxis);

                vis.append("svg:g")
                    .attr("class", "y axis")
                    .attr("transform", "translate(" + (MARGINS.left) + ",0)")
                    .call(yAxis);

                //Aggiungi GRID
                function make_x_axis() {        
                    return d3.svg.axis()
                        .scale(xScale)
                        .orient("bottom")
                        .ticks(10)
                }

                function make_y_axis() {        
                    return d3.svg.axis()
                        .scale(yScale)
                        .orient("left")
                        .ticks(10)
                }

                vis.append("svg:g")         
                    .attr("class", "grid")
                    .attr("transform", "translate(0," + HEIGHT + ")")
                    .call( make_x_axis()
                        .tickSize(-HEIGHT, 0, 0)
                        .tickFormat("")
                    )
                vis.append("svg:g")         
                    .attr("class", "grid")
                    .call( make_y_axis()
                        .tickSize(-WIDTH, 0, 0)
                        .tickFormat("")
                    )

                var lineGen = d3.svg.line()
                    .x(function(d) {
                        return xScale(d.year);
                    })
                    .y(function(d) {
                        return yScale(d.sale);
                    })
                    .interpolate("basis"); //linear

                lSpace = WIDTH/dataGroup.length;

                dataGroup.forEach(function(d, i) {
                    color = "hsl(" + Math.random() * 360 + ",100%,50%)";

                    vis.append('svg:path')
                        .attr('d', lineGen(d.values))
                        .attr('stroke', color)
                        .attr('stroke-width', 2)
                        .attr('id', 'line_'+d.key)
                        .attr('fill', 'none');
                    vis.append("text")
                        .attr("x", (lSpace / 2) + i * lSpace)
                        .attr("y", HEIGHT)
                        //.style("stroke", "black")
                        .style("fill", color)
                        .attr("class", "legend").on('click', function() {
                                                    var active = d.active ? false : true;
                                                    var opacity = active ? 0 : 1;

                                                    d3.select("#line_" + d.key).style("opacity", opacity);

                                                    d.active = active;
                                                })
                        .text(d.key);
                });

                function zoomed() {
                    vis.select(".x.axis").call(xAxis);
                    vis.select(".y.axis").call(yAxis);   
                    vis.selectAll('path.line').attr("d",  function(d) {return line(d.values)}); **-> HERE I WOULD ZOOM/TRANSFORM**
                }

                var zoom = d3.behavior.zoom()
                    .x(xScale)
                    .y(yScale)
                    .scaleExtent([1, 10])
                    .on("zoom", zoomed);

                vis.call(zoom)
            }
            InitChart();
        </script>
    </div>

</div>

1 个答案:

答案 0 :(得分:1)

应该改变两件事以使其发挥作用。

首先在缩放功能中,您最终得到一个空的选择,因为路径没有线类。在生成路径时将路线类添加到路径,以使.selectAll('path.line')工作。

其次,您没有将数据绑定到路径,因此稍后您无法在缩放功能中使用它。如果将匿名函数作为.attr的第二个参数传递,那么此函数的第一个参数(在您的情况下为d)将是绑定到选择的数据。要使这条线工作:

vis.selectAll('path.line').attr("d", function(d) {return line(d.values)});

您必须向路径添加数据。一种方法是这样的:

vis.append('svg:path').datum(d)

但是,有一种更好的方法来绑定数据并输入新元素而不是您使用的forEach循环。我推荐由Scott Murray撰写的this非常有用的教程,解释了d3数据绑定。

以下是更新后的jsfiddle