我正在尝试模拟动画/转换的折线图,如
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);
yAxis = d3.axisLeft(yScale);
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 };