javascript - "stacked"上的 `translate()` 转换偶尔会卡顿 (v4.0.0-alpha40)

标签 javascript d3.js babeljs

问题: SCSS

我有一个 D3 v4.0.0-alpha.40 图表,它会定期(不是在每一帧上):

  1. 获取新的数据点
  2. 删除旧数据点
  3. 重置转换并设置translate(null)
  4. 开始新的 transition() 新的滚动,因为它获得新的值。
// Animation
function animateOnce(period) {
    // Data: Add new, and remove old
    data.unshift(Math.random());
    data.pop();
    // Do 2 transitions...
    path
      .attr("d", line)
      .transition() /* ...reset */
        .attr("transform", null)
        .duration(0)
      .transition()/* ...scroll across */
        .duration(period)
        .ease(d3.easeLinear)
        .attr("transform", `translate(${x(1)})`)
};

// Animation looper
function animate() {
    setTimeout(_=> {
        animateOnce(PERIOD);
    animate();
    },
  PERIOD);
}

但是转换似乎执行不干净 - 每隔几秒就会出现一个 SCSS

我之前在使用 D3 v3 时遇到过这个问题,但我相信我通过添加重置转换(上面的第 3 步)修复了它。不幸的是,我没有使用 D3 的经验,我不确定如何解决这个问题。

看到了

This jsFiddle是我的图表的近似值,您应该能够看到偶尔的颠簸。

注意: fiddle 使用 setTimeout 而我的实际图表是 react 组件,使用 componentDidUpdate() 更新。

编辑 1:改进使用中断

Improved jsFiddle

在阅读文档时(如@Ashitaka 所建议的那样)- 我找到了 interrupt() .这会正确终止转换,并且可能是实现上述第 3 步(重置转换)的“v4 方式”。

// Animation
function animateOnce(period) {
    // Data: Add new, and remove old
    data.unshift(Math.random());
    data.pop();
    // Do 2 transitions...
    path
      .attr("d", line)
      .interrupt() /* ...reset */
      .attr("transform", null)
      .transition()/* ...scroll across */
        .duration(period)
        .ease(d3.easeLinear)
        .attr("transform", `translate(${x(1)})`)
};

这改善了 SCSS (我假设是由于竞争性转换),将它们变成小的口吃

我想了解(我假设是 1 帧)卡顿是在哪里引入的。所以我现在将其打开。

最佳答案

在 Mike Bostock 的帖子中 Working with Transitions ,他写道:

For a given element, transitions are exclusive: only one transition can be running on the element at the same time. Starting a new transition on the element stops any transition that is already running.

现在,我在提供的代码中检测到两个问题:

  1. 路径变换重置正在动画化(即使持续时间为 0)。这个新的转换取消了之前的转换。这可以通过更改来解决:

    path
      .attr("d", line)
      .transition()
        .attr("transform", null)
        .duration(0)
    

    到:

    path
      .attr("d", line)
      .attr("transform", null)
    
  2. animateOnce 函数的调用周期与 D3 的转换和 a transition tick lasts for ~17 ms 相同。 .这个新的转换也取消了之前的转换。这可以通过更改来解决:

    function animate() {
      setTimeout(_=> {
        animateOnce(PERIOD);
        animate();
      },
      PERIOD);
    }
    

    到:

    function animate() {
      setTimeout(_=> {
        animateOnce(PERIOD);
        animate();
      },
      PERIOD + 20);
    }
    

    可以用 setInterval 进一步重构到:

    function animate() {
      setInterval(animateOnce, PERIOD + 20, PERIOD);
    }
    

这 2 项更改应该可以解决卡顿问题。尽管如此,每 80 毫秒更新一次该折线图总是会给某人的计算机或智能手机带来负担。我建议您仅每 200 毫秒左右更新一次。

编辑:我做了一些实验,发现 Firefox 上仍然存在一些卡顿。因此,还有几点需要考虑:

  1. transform 属性设置为 null 实际上会创建一个新的 layer .这可以通过更改来解决:

    .attr("transform", null)
    

    到:

    .attr("transform", "translate(0)")
    
  2. 每次调用 animateOnce 函数时都会重新创建转换字符串。我们可以在 animateOnce 之外预先计算它们,然后重用它们。这可以通过更改来解决:

    .attr("transform", "translate(0)")
    .attr("transform", `translate(${x(1)})`)
    

    到:

    // outside the animateOnce function:
    let startStepAttrs = { transform: "translate(0)" },
        endStepAttrs   = { transform: `translate(${x(1)})` };
    
    // inside the animateOnce function:
    .attr(startStepAttrs)
    .attr(endStepAttrs)
    

关于javascript - "stacked"上的 `translate()` 转换偶尔会卡顿 (v4.0.0-alpha40),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37326252/

相关文章:

javascript - AngularJS 中的新窗口

javascript - 当用户使用 jquery 聚焦到 textarea 时显示按钮

d3.js - 为什么刷机阻止dc.js barChart toolTips出现?

d3.js - SVG 路径超出 d3 画笔上的图表区域

javascript - 将所选元素移动到末尾

webpack - 部分导入 antd 包不起作用

javascript - 语法错误 : Unexpected token import - Node. js

javascript - 无法返回表单提交为 false

javascript - fadeIn() 值到一个输入字段,如何?

javascript - 如何在 React + Babel 中允许异步函数?