代码之家  ›  专栏  ›  技术社区  ›  1252748

新的、更大的数据集在折线图上不会转换为SVG,它们会立即出现

  •  0
  • 1252748  · 技术社区  · 6 年前

    我正在尝试模拟动画/转换的折线图,如 this demo (没有圆点)。此外,我还试图在react组件中使用它,其中update方法可以被另一个组件调用,使d3的功能类似于helper函数,而不是像演示那样自上而下运行。

    问题是,当x轴(日期范围)增大时,与新添加的日期相关联的行/数据不会“动画化”:它们会立即出现在图表上。这会产生一种效果,即已经存在的线会动画化到新位置,并在新出现的线上移动,使丑陋的重叠大约半秒钟。

    如果你按 更新 按钮上 the CodeSandbox here . 它是随机生成的虚拟数据,因此您可能需要单击它几次才能看到效果。

    如何平滑地将转换应用到新数据?

    相关D3代码:

    import * as d3 from 'd3';
    
    var line;
    var svg;
    var plotLine;
    var xScale, yScale;
    var xAxis, yAxis;
    var parseTime = d3.timeParse('%d-%b-%y');
    var displayDateFormat = '%d-%b-20%y';
    
    function transormData(datum) {
      return {
        date: parseTime(datum.date),
        close: parseInt(datum.close, 10)
      };
    }
    export default function sharedChartFn(firstRun, data) {
      data = data.map(transormData);
    
      var margin = {
          top: 20,
          right: 20,
          bottom: 30,
          left: 50
        },
        width = 800 - margin.left - margin.right,
        height = 400 - margin.top - margin.bottom;
    
      xScale = d3
        .scaleLinear()
        .range([0, width])
        .domain(
          d3.extent(data, function(d) {
            return d.date;
          })
        )
        .nice();
    
      yScale = d3
        .scaleLinear()
        .range([height, 0])
        .domain(
          d3.extent(data, function(d) {
            return d.close;
          })
        )
        .nice();
    
      xAxis = d3.axisBottom(xScale).ticks(12);
      yAxis = d3.axisLeft(yScale).ticks((12 * height) / width);
    
      plotLine = d3
        .line()
        .curve(d3.curveMonotoneX)
        .x(function(d) {
          return xScale(d.date);
        })
        .y(function(d) {
          return yScale(d.close);
        });
    
      svg = d3
        .select('#plot')
        .append('svg')
        .attr('width', width + margin.left + margin.right)
        .attr('height', height + margin.top + margin.bottom);
    
      svg
        .append('g')
        .attr('class', 'x axis ')
        .attr('id', 'axis--x')
        .attr(
          'transform',
          'translate(' + margin.left + ',' + (height + margin.top) + ')'
        )
        .call(xAxis.tickFormat(d3.timeFormat(displayDateFormat)));
    
      svg
        .append('g')
        .attr('class', 'y axis')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
        .attr('id', 'axis--y')
        .call(yAxis);
    
      line = svg
        .append('g')
        .append('path')
        .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
        .datum(data)
        .attr('d', plotLine)
        .style('fill', 'none')
        .style('stroke', 'brown');
    }
    
    function update(newData) {
      newData = newData.map(transormData);
      console.log('parsed', newData);
      debugger;
      xScale
        .domain(
          d3.extent(newData, function(d) {
            return d.date;
          })
        )
        .nice();
      yScale
        .domain(
          d3.extent(newData, function(d) {
            return d.close;
          })
        )
        .nice();
    
      xAxis = d3.axisBottom(xScale); //.ticks(12);
      yAxis = d3.axisLeft(yScale); // .ticks((12 * height) / width);
    
      svg
        .select('.x')
        .transition()
        .duration(750)
        .call(xAxis.tickFormat(d3.timeFormat(displayDateFormat)));
      svg
        .select('.y')
        .transition()
        .duration(750)
        .call(yAxis);
    
      line
        .datum(newData)
        .transition()
        .duration(750)
        .attr('d', plotLine)
        .style('fill', 'none')
        .style('stroke-width', '2px');
    }
    
    export { update };
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   rioV8    6 年前

    动画在生成的路径属性上完成。如果更新中有更多的点,则这些点不会设置动画,而是绘制在正确的位置。

    解决方案:在旧的xscale/yscale上绘制新点。现在这条路径有相同数量的数字。更改XScale/YScale。将线设置为这些新比例的动画。

    function update(newData) {
      newData = newData.map(transormData);
      line
        .datum(newData)
        .attr('d', plotLine)
        .style('fill', 'none')
        .style('stroke-width', '2px');
    
      console.log('parsed', newData);
      .....
      // change scales
      ....
      line
        .transition()
        .duration(750)
        .attr('d', plotLine);
    }