我正在使用具有滑动 x 轴的 d3 实现图表。 Demo
问题是,当我切换到另一个选项卡,然后返回(比如 10 秒后)时,d3 似乎试图重放丢失的过渡,这导致轴的行为非常尴尬。参见 here .
迈克博斯托克 mentions that :
D3 4.0 fixes this problem by changing the definition of time. Transitions don’t typically need to be synchronized with absolute time; transitions are primarily perceptual aids for tracking objects across views. D3 4.0 therefore runs on perceived time, which only advances when the page is in the foreground. When a tab is backgrounded and returned to the foreground, it simply picks up as if nothing had happened.
这真的是固定的吗?我做错了什么吗?
const timeWindow = 10000;
const transitionDuration = 3000;
const xScaleDomain = (now = new Date()) =>
[now - timeWindow, now];
const totalWidth = 500;
const totalHeight = 200;
const margin = {
top: 30,
right: 50,
bottom: 30,
left: 50
};
const width = totalWidth - margin.left - margin.right;
const height = totalHeight - margin.top - margin.bottom;
const svg = d3.select('.chart')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight)
.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
svg
.append('rect')
.attr('width', width)
.attr('height', height);
// Add x axis
const xScale = d3.scaleTime()
.domain(xScaleDomain(new Date() - transitionDuration))
.range([0, width]);
const xAxis = d3.axisBottom(xScale);
const xAxisSelection = svg
.append('g')
.attr('transform', `translate(0, ${height})`)
.call(xAxis);
// Animate
const animate = () => {
xScale.domain(xScaleDomain());
xAxisSelection
.transition()
.duration(transitionDuration)
.ease(d3.easeLinear)
.call(xAxis)
.on('end', animate);
};
animate();
svg {
margin: 30px;
background-color: #ccc;
}
rect {
fill: #fff;
outline: 1px dashed #ddd;
}
<script src="https://unpkg.com/d3@4.4.1/build/d3.js"></script>
<div class="chart"></div>
最佳答案
问题不在于 D3 转换。这里的问题是 new Date()
。
每次您转到另一个选项卡时,过渡都会暂停。到目前为止,一切都很好。但是,当您返回图表时,比方说,20 秒后,您会得到一个新日期,即当前日期……但是您的 timeWindow
和您的 transitionDuration 是一样的
:
const timeWindow = 10000;
const transitionDuration = 3000;
const xScaleDomain = (now = new Date()) => [now - timeWindow, now];
这使得轴向前跳得更快,因为域中任何一点的旧值和新值之间的差异不再是 3 秒。
这里有一个非常简单的解决方案,太粗糙,需要改进,只是为了告诉你问题出在 new Date()
上。在这个解决方案(同样,远非完美)中,我手动将每个动画中的日期设置为跳转 10 秒,无论您在另一个选项卡中停留多长时间:
var t = xScale.domain()[1];
t.setSeconds(t.getSeconds() + 10);
xScale.domain([xScale.domain()[1], t]);
这是 CodePen:http://codepen.io/anon/pen/GrjMxy?editors=0010
使用您的代码的更好解决方案是更改 timeWindow
和 transitionDuration
以考虑新的 new Date()
和旧的 new Date()
(即用户在另一个选项卡中停留的时间)。
关于d3.js - 如何修复 d3 v4 中的重播转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41668051/