Новые, более крупные наборы данных на линейном графике не переходят на SVG, они сразу появляются - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь эмулировать анимированную / переходную линейную диаграмму, показанную в этой демонстрации (без точек).Кроме того, я пытаюсь использовать его в реактивном компоненте, где метод обновления может вызываться другим компонентом, что делает d3 вроде вспомогательных функций, а не просто запускается сверху вниз, как это делает демонстрация.

Проблема заключается в том, что при увеличении оси x (диапазона дат) строки / данные, связанные с вновь добавленными датами, не «анимируются в»: они появляются на диаграмме мгновенно.Это имеет эффект, когда линия, которая уже существует, оживляет свою новую позицию и перемещается по вновь появившейся линии, создавая уродливое перекрытие примерно на полсекунды.

Это можно увидеть, если нажать Обновление Кнопка на CodeSandbox здесь .Это случайные сгенерированные фиктивные данные, поэтому вам, возможно, придется щелкнуть по ним несколько раз, чтобы увидеть эффект.

Как плавно применить переход к новым данным?

Соответствующий код 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 Ответ

0 голосов
/ 20 ноября 2018

Анимация выполняется на сгенерированных атрибутах пути.Если у вас есть больше точек в обновлении, они не анимируются, а отображаются в правильном месте.

Решение: нарисуйте новые точки на старом 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);
}
...