【发布时间】:2021-11-20 20:32:06
【问题描述】:
下面的代码动画一个 SVG 圆圈改变颜色并按预期工作。
如果对SVG.addAnimatedCircle(this.root) 的调用是从callback 方法内部(而不是它在下面的位置,在constructor 内部)进行的,则动画在文档加载时开始 - 因此除非窗口被点击——而不是在事件被触发时。
class SVG {
constructor() {
const root = document.createElementNS(
'http://www.w3.org/2000/svg', 'svg');
root.setAttribute('viewBox', '-50 -50 100 100');
this.root = root;
this.callback = this.callback.bind(this);
window.addEventListener('click', this.callback);
SVG.addAnimatedCircle(this.root);
}
callback() {
// SVG.addAnimatedCircle(this.root);
}
static addAnimatedCircle(toElement) {
const el = document.createElementNS(
'http://www.w3.org/2000/svg', 'circle');
el.setAttribute('cx', '0');
el.setAttribute('cy', '0');
el.setAttribute('r', '10');
el.setAttribute('fill', 'red');
toElement.appendChild(el);
const anim = document.createElementNS(
'http://www.w3.org/2000/svg', 'animate');
anim.setAttribute('attributeName', 'fill');
anim.setAttribute('from', 'blue');
anim.setAttribute('to', 'red');
anim.setAttribute('dur', '3s');
el.appendChild(anim);
}
}
const svg = new SVG();
document.body.appendChild(svg.root);
(当然,上面不需要在class 中,我正在简化一个更复杂的类)。
这是为什么呢?动画不应该在元素创建并添加到 DOM 时开始吗?
【问题讨论】:
-
这取决于是否运行任何其他动画来移动时间线。
-
不涉及其他动画。这就是为什么我将我的课程简化为一个最小的独立示例来演示这个问题。
-
有趣的观察。我添加了带有静态 SVG 的简化测试用例,并在 SVG 节点“之后”立即从脚本触发警报:在我的 Firefox 中,它在模态下显示黑色非动画圆圈。 Chrome 会等到警报被解除以绘制(和动画)SVG 并且随后的警报暂停动画(与 Firefox 不同)。
-
好吧,但这次不是问题,恰恰相反:我故意使用警报来推迟加载事件,并查看 SVG 在“加载前”/使用 main 时的外观和行为线程暂停。顺便说一句,运行测试用例几次,我得到了一次红色圆圈(没有动画的状态),所以这似乎是一个不错的竞争条件。 (我没有深入了解 JS 线程、HTML 渲染和 SVG SMIL 计时器如何/是否相互关联,只是想添加示例以供使用。)
-
我没有逐渐加载的应用程序。问题比这简单得多。我的原始代码可以按原样复制和粘贴,并且可以清楚地说明问题,不需要额外的组件。然而,经过大量搜索,结果发现代码缺少一些关键的东西:
anim.setAttribute('begin', 'indefinite')延迟动画开始,document.querySelector('animate').beginElement()(在回调内部)。然后beginElement方法在事件触发时触发动画。我应该把这个作为答案吗?
标签: javascript svg