动画d3.js折线图路径退出

animate d3.js line chart path exit

本文关键字:路径 退出 折线图 js d3 动画      更新时间:2023-09-26

我正在用d3创建一个简单的折线图,我试图在做数据更新时动画线(现在有一条线)。

// https://bl.ocks.org/mbostock/3883245
// http://bl.ocks.org/d3noob/7030f35b72de721622b8
function LineChart(options) {
    // Mike Bostock margin conventions.
    // See http://bl.ocks.org/mbostock/3019563 for more info.
    const margin = this.margin = {
        top: 20,
        right: 20,
        bottom: 30,
        left: 40
    };
    // Used by some of the functions that get a different context when called by d3.
    const thisRef = this;
    this.width = options.width - margin.left - margin.right;
    this.height = options.height - margin.top - margin.bottom;
    this.x = d3.time.scale()
        .range([0, this.width]);
    this.y = d3.scale.linear()
        .range([this.height, 0]);
    this.xAxis = d3.svg.axis()
        .scale(this.x)
        .orient('bottom');
    this.yAxis = d3.svg.axis()
        .scale(this.y)
        .orient('left');
    this.line = d3.svg.line()
        // https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes#line_interpolate
        .interpolate(options.interpolate)
        .x(function(d) {
            return thisRef.x(d.date);
        })
        .y(function(d) {
            return thisRef.y(d.value);
        });
    // Create an SVG element (appended to `#chart`):
    // 1. set size;
    // 2. add a `g` element (as in a group) - the `svg` variable here is a `g` element now;
    // 3. set the transform on `<g>` (not on `<svg>`).
    this.svg = d3.select(options.target)
        .append('svg')
        .attr('width', this.width + margin.left + margin.right)
        .attr('height', this.height + margin.top + margin.bottom)
        .append('g')
        .attr('transform', `translate(${margin.left}, ${margin.top})`);
    // Add x axis.
    this.svg.append('g')
        .attr('class', 'x axis')
        .attr('transform', `translate(0, ${this.height})`)
    // Add y axis (with a label).
    this.svg.append('g')
        .attr('class', 'y axis')
        // Just for the title (ticks are automatic).
        .append('text')
        // Rotate the text.
        .attr('transform', 'rotate(-90)')
        .attr('y', 6)
        .attr('dy', '.71em')
        .style('text-anchor', 'end')
        .text('Price ($)');
}
LineChart.prototype.update = function update(data) {
    const thisRef = this;
    this.x.domain(d3.extent(data, function(d) {
        return d.date;
    }));
    this.y.domain(d3.extent(data, function(d) {
       return d.value;
    }));
    this.svg.select('.x.axis')
        .transition()
        .call(this.xAxis);
    this.svg.select('.y.axis')
        .transition()
        .call(this.yAxis)
    const lines = this.svg.selectAll('.line')
        .data(data, function(d) {
            return d.label;
        });
    lines.enter()
        .append('path')
        .attr('class', 'line');
    lines.transition()
        .duration(1500)
        .attr('d', this.line(data));
    lines.exit()
        .remove();
}

你可以在这里看到一个运行的例子。

在这个例子中,有一个3000毫秒的延迟,之后你将看到更新和动画。

但是我有一个小问题,一行的一部分被抛出而没有任何动画。

我很难弄清楚发生了什么,因为我不是很有经验的d3,一些帮助将是感激:)

D3动画DOM元素。在您的示例中只有一个DOM元素(一行),D3认为您更改了这一行(1500ms)。它不知道如何处理丢掉的分数(或增加的分数)。SVG路径段并不是动画的单位。当您更改数据时,'enter'和'exit'选择不会改变('exit'选择为空)。

你有两个选择:

  1. 在删除数据之前,创建一个额外的行(DOM元素)与缺失的点,并单独动画。
  2. 创建该线的段(因此,制作多条线,每2个点一条线),并将它们动画化(参见http://jsfiddle.net/L1tLot0v/15/)。不幸的是,这样的插值就不会那么酷了。

    var segmentedData = segments(data);
    const lines = this.svg.selectAll('.line')
        .data(segmentedData, function(d) {
            return d[0].date;
    });
    var lineFunc = this.line;
    lines.enter()
        .append('path')
        .attr('class', 'line')
        .style("opacity", 0.0)
        .attr('d', function(d) {
          return lineFunc(d)})
        .transition()
        .duration(1000)
        .style("opacity", 1.0);
    lines.exit()
      .transition()
      .duration(1000)
      .style("opacity", 0.0)
      .remove();