如何使用d3选择/连接方法更改折线图?

时间:2017-07-09 00:46:50

标签: javascript d3.js

我正在使用v4。

我想动态更改折线图的数据,但我无法弄清楚如何将数据传递到d元素的path属性。这不起作用(没有画线):

    draw_line(data) {
        let selection = this.svg.select('path.line').datum(data);
        selection.enter()
             .append('path')
             .attr('class', 'line')
             .attr('d', this.line);
        selection
            .transition(this.transition)
            .attr('d', this.line);
    }

以下内容确实有效,但它似乎并不惯用(不使用enter()exit()等。

    draw_line(data) {
        let path = this.svg.select('path.line');
        if (path.empty()) {
            this.svg
                .append('path')
                .datum(data)
                .attr('class', 'line')
                .attr('d', this.line);
        } else {
             path
                .datum(data)
                .transition(this.transition)
                .attr('d', this.line);
        }
    }

我确定我错过了一些明显的东西......?

以下内容不应与该问题相关,但包含在内以供参考。 构造函数和调用方法如下所示:

class LineGraph {
    constructor(w, h, location) {
        this.margin = {top: 50, right: 50, bottom: 50, left: 50};
        this.outer_width = w;
        this.outer_heigth = h;
        this.width = this.outer_width - this.margin.left - this.margin.right;
        this.height = this.outer_heigth - this.margin.top - this.margin.bottom;

        this.svg = d3.select(location)
                     .append("svg")             // append the svg object to location
                       .attr("width", w)
                       .attr("height", h)
                     .append("g")               // appends a 'group' element to 'svg'
                        .attr("transform", `translate(${this.margin.left}, ${this.margin.top})`);
    }

    draw(data) {
        this.transition = d3.transition()
                            .duration(2000);

        // set the ranges
        this.x = d3.scaleTime().range([0, this.width]);
        this.bottomAxis = d3.axisBottom(this.x).ticks(d3.timeWeek);

        this.y = d3.scaleLinear().range([this.height, 0]);
        this.leftAxis = d3.axisLeft(this.y);

        this.line = d3.line()
          .x(d => this.x(d.date))
          .y(d => this.y(d.value));

        // this.draw_axes(data);
        this.draw_line(data);
    }

,调用如下:

let graph = new LineGraph(500, 500, '#content');
let parse_time = d3.timeParse('%d-%b-%y');
let data1 = [
    {date: parse_time('1-May-12'), value: 158.13},
    {date: parse_time('30-Apr-12'), value: 153.98},
    {date: parse_time('27-Apr-12'), value: 167.00}
];
let data2 = [
    {date: parse_time('2-May-12'), value: 242.42},
    {date: parse_time('1-May-12'), value: 158.13},
    {date: parse_time('30-Apr-12'), value: 153.98},
    {date: parse_time('27-Apr-12'), value: 167.00} 
];
graph.draw(data1.sort((a, b) => a.date - b.date));

setTimeout(() => {
    graph.draw(data2.sort((a, b) => a.date - b.date));
}, 2000);

1 个答案:

答案 0 :(得分:2)

data()方法不同,datum()不计算连接。根据{{​​3}}:

  

与selection.data不同,此方法不计算连接,也不影响索引或输入和退出选择。

此外,selectselectAll在分组和数据传播方面表现不同。您应该使用selectAll,即使图表中只有一行。看看这张表:

+--------------------+----------------------------------+----------------------------+
| Method             |              select()            |         selectAll()        |
+--------------------+----------------------------------+----------------------------+
| Selection          | selects the first element        | selects all elements that  |
|                    | that matches the selector string | match the selector string  |
+--------------------+----------------------------------+----------------------------+
| Grouping           | Does not affect grouping         | Affects grouping           |
+--------------------+----------------------------------+----------------------------+
| Data propagation   | Propagates data                  | Doesn't propagate data     |
+--------------------+----------------------------------+----------------------------+

因此,您的第一个代码段应为:

draw_line(data) {

    let selection = this.svg.selectAll('path.line')
    //'selectAll' here ----------^
        .data([data]);
        // ^--- 'data' instead of 'datum'

    selection.enter()
         .append('path')
         .attr('class', 'line')
         .attr('d', this.line);

    selection.transition(this.transition)
        .attr('d', this.line);

}