将多折线图创建为可重用组件

creating multi-line charts as a reusable component

本文关键字:组件 折线图 创建      更新时间:2024-02-07

我想我差不多到了。我有一个单行的工作版本,可以动态更新,但在多行部分遇到了问题。我认为这与_selection.each过滤数据的方式有关。但不确定从这里开始的最佳方式。这里的例子(在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;
}

我认为对此可能有不同的意见,但我不会使用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()。第一个将期望单行(数组)的数据,第二个将期望数组(多行)的数组。在内部,它们总是被表示为数组的数组。这样,图表绘制代码总是希望绘制多行数据,但有时数据只有一行。