问题: SCSS
我有一个 D3 v4.0.0-alpha.40 图表,它会定期(不是在每一帧上):
- 获取新的数据点
- 删除旧数据点
- 重置转换并设置
translate(null)
- 开始新的
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:改进使用中断
在阅读文档时(如@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.
现在,我在提供的代码中检测到两个问题:
路径变换重置正在动画化(即使持续时间为
0
)。这个新的转换取消了之前的转换。这可以通过更改来解决:path .attr("d", line) .transition() .attr("transform", null) .duration(0)
到:
path .attr("d", line) .attr("transform", null)
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 上仍然存在一些卡顿。因此,还有几点需要考虑:
将
transform
属性设置为null
实际上会创建一个新的 layer .这可以通过更改来解决:.attr("transform", null)
到:
.attr("transform", "translate(0)")
每次调用
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/