创建多线图作为可重用组件

时间:2013-12-03 16:45:20

标签: javascript d3.js

我想我差不多了。我有一个可以动态更新的单行的工作版本,但是很难进入多线部分。我认为这与在_selection.each上过滤数据的方式有关。不知道从这里开始的最佳方式。这里找到的例子(Drawing Multiple Lines in D3.js)似乎没有太多工作就解决了这个问题。

这是jsfiddle,但代码如下所示: http://jsfiddle.net/seoulbrother/NhK43/

提前致谢。此外,我也希望听到有关此问题的最佳做法。

因此,如果我有一个矩阵的页面,其中每一行代表一个时间序列:

<html>
<body>
<div id="container"><div id="viz"></div></div>
</body>
</html>

<script type="text/javascript">
var matrix = [
 [23,12,44,22,12,33,14,76,45,55,66,55],
 [33,22,11,88,32,63,13,36,35,51,26,25]
];
</script>

我用这个来打电话:

mult_line = d3.graph.line(500, 250, "#viz");
d3.select("#container").datum(matrix).call(mult_line);

其中d3.graph.line为:

d3.graph.line = function module(w, h, id) {
    var svg;
    var margin = {top: 10, right: 20, bottom: 20, left: 40},
        width = w - margin.left - margin.right,
        height = h - margin.top - margin.bottom;

    function chart(_selection) {
       _selection.each(function(_data) {
            console.log(_data);
            var x = d3.scale.linear().domain([1, _data.length]).range([0, width]);
            var y = d3.scale.linear().domain([0, 100]).range([height, 0]);

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

            var line = d3.svg.line()
                .x(function(d,i) { return x(i+1); })
                .y(function(d) { return y(d); });

            if (!svg){
                svg = d3.select(id).append("svg")
                    .attr("width", width + margin.left + margin.right)
                    .attr("height", height + margin.top + margin.bottom)
                    .append("g")
                    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

                svg.append("path")
                    .attr("class","line")
                    .attr("d", line(_data));

                svg.append("g")
                      .attr("class", "x-axis")
                      .attr("transform", "translate(0," + height + ")")
                      .call(xAxis);

                svg.append("g")
                      .attr("class", "y-axis")
                      .call(yAxis);
            }

            var line_m = d3.selectAll("path.line")
                .data(_data);

            line_m.transition()
                .duration(1000)
                .attr('d', line(_data));

            line_m.enter().append("path")
                .attr("d",line(_data));

            update_axis();
            function update_axis() {
                d3.select(".x-axis").call(xAxis);
            }
        });
    }
    return chart;
}

1 个答案:

答案 0 :(得分:1)

我认为可能会有不同的意见,但我不会使用selection.datum()作为将数据传递到图表组件的机制。相反,我会添加一个.data() setter方法作为多行组件的属性。我会对宽度,高度等做同样的事情。这是d3组件的实现方式(例如,查看d3.svg.axis的源代码)。然后您的图表创建将如下所示:

mult_line = d3.graph.line()
  .width(500)
  .height(250)
  .id("#viz")
  .data(matrix);
d3.select("#container").call(mult_line);

您可以对此进行优化,以便有两种多行数据设置方法:.data().multilineData()。第一个是期望单行(数组)的数据,第二个期望数组的数组(多行)。在内部,它们总是被表示为数组数组。这样,图表绘制代码总是希望绘制多行数据,有时数据只有一行。