为何SVG动画会在页面加载时触发而非DOM元素插入时触发?
问题原因
这个现象是SVG的SMIL动画默认计时规则导致的,和你理解的「元素插入DOM才启动动画」的逻辑有差异:
<animate>元素的begin属性默认值为0s,这个时间是相对于它所属的SVG根元素的文档时间线起点计算的,不是相对于自身被插入DOM的时间点。- 你代码的执行顺序是:先执行
new SVG()完成实例化,再把SVG根元素插入到页面DOM中,SVG根元素插入页面的瞬间,它的时间线就从0开始计时。 - 如果你把
SVG.addAnimatedCircle(this.root)移到点击回调中:- 页面加载完成后SVG已经插入DOM,时间线一直在往前走
- 等到你触发点击事件时,SVG的时间线已经走了超过动画时长(3秒)
- 此时新插入的
<animate>元素的启动时间是0s,已经远早于当前时间,动画会直接判定为执行完毕,你自然看不到任何过渡效果,只会看到最终的红色圆形。
如果你希望动画在元素插入时才启动,只需要修改addAnimatedCircle方法里的动画配置:
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'); // 新增:指定动画需要手动触发 anim.setAttribute('begin', 'indefinite'); el.appendChild(anim); // 插入元素后手动启动动画 anim.beginElement(); }
内容的提问来源于stack exchange,提问作者Cirrocumulus
相关产品推荐
相关产品推荐

