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

Javascript 设置d3.js折线图路径退出动画,javascript,d3.js,linechart,Javascript,D3.js,Linechart,我正在用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/301

我正在用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();
}
//https://bl.ocks.org/mbostock/3883245
// http://bl.ocks.org/d3noob/7030f35b72de721622b8
功能折线图(选项){
//迈克·博斯托克。
//看http://bl.ocks.org/mbostock/3019563 更多信息。
常量边距=此。边距={
前20名,
右:20,,
底数:30,
左:40
};
//被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()
.范围([0,此宽度]);
this.y=d3.scale.linear()
.范围([this.height,0]);
this.xAxis=d3.svg.axis()
.scale(此.x)
.orient(“底部”);
this.yAxis=d3.svg.axis()
.scale(this.y)
.东方(左);
this.line=d3.svg.line()
// https://github.com/d3/d3-3.x-api-reference/blob/master/SVG-Shapes#line_interpolate
.插值(选项.插值)
.x(功能(d){
返回此参考x(日期);
})
.y(功能(d){
返回此参考y(d值);
});
//创建SVG元素(附加到`#图表`):
//1.设定尺寸;
//2.添加一个'g'元素(如在组中)-'svg'变量现在是'g'元素;
//3.将转换设置为``(而不是``)。
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})`);
//添加x轴。
this.svg.append('g'))
.attr('class','x轴')
.attr('transform','translate(0,${this.height})`)
//添加y轴(带标签)。
this.svg.append('g'))
.attr('class','y轴')
//仅用于标题(勾号是自动的)。
.append('文本')
//旋转文本。
.attr('transform'、'rotate(-90'))
.attr('y',6)
.attr('dy','.71em'))
.style('text-anchor','end')
.text('价格($));
}
LineChart.prototype.update=函数更新(数据){
const thisRef=this;
这个.x.domain(d3.extent)(数据,函数(d){
返回日期;
}));
此.y.域(d3.范围(数据、函数(d)){
返回d值;
}));
this.svg.select(“.x.axis”)
.transition()
.调用(this.xAxis);
this.svg.select(“.y.axis”)
.transition()
.call(this.yAxis)
const lines=this.svg.selectAll(“.line”)
.数据(数据、功能(d){
返回d.标签;
});
行。输入()
.append('路径')
.attr(“类”、“行”);
行。转换()
.持续时间(1500)
.attr('d',这一行(数据));
行。退出()
.remove();
}
您可以看到一个正在运行的示例

在本例中,有一个
3000
ms延迟,之后您将看到更新和动画

但我有一个小问题,一部分线路在没有任何动画的情况下被抛出


我很难弄清楚到底发生了什么,因为我对d3不是很有经验,希望能得到一些帮助:)

d3为DOM元素制作动画。在您的示例中只有一个DOM元素(一行),D3认为您更改了这一行(1500毫秒)。它不知道如何处理丢弃的点(或添加的点)。SVG路径段不是动画的一个单元。更改数据时,“输入”和“退出”选项不会更改(“退出”选项为空)

您有两个选择:

  • 在删除一段数据之前,创建一条包含缺失点的额外直线(DOM元素),并分别设置动画
  • 创建该直线的线段(因此,创建多条直线,每2个点一条直线),并为其设置动画(请参见)。不幸的是,那么插值就没有那么酷了

    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();