d3.js - 如何修复 d3 v4 中的重播转换?

标签 d3.js

我正在使用具有滑动 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

使用您的代码的更好解决方案是更改 timeWindowtransitionDuration 以考虑新的 new Date() 和旧的 new Date()(即用户在另一个选项卡中停留的时间)。

关于d3.js - 如何修复 d3 v4 中的重播转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41668051/

相关文章:

javascript - 在 d3 Canvas map 上绘制圆弧时出现问题

d3.js - 如何根据形状场值向 D3 力有向图添加两种不同的形状?

javascript - flask +d3.js : Passing multiple datasets to html

javascript - d3js选择带有特定文本标签的圆圈

javascript - 将 html 输入值添加到 d3js

d3.js - dc.js 系列图表多线

javascript - 检索数据绑定(bind) d3

javascript - .data(...) 字段的 D3js 值在窗口大小调整时不会更改。有办法改变吗?

javascript - D3.js:将节点放置在其他节点内

javascript - 如何获取d3.ease的返回值?