animateMotion的fill="freeze"属性在Chrome浏览器中无法正常生效
SVG animateMotion 在 Chrome 中动画结束后复位的兼容性问题
我之前也踩过这个Chrome的SVG动画坑!你编写的这段SVG代码在Firefox 60.0.1里能正常让<path>停留在<animateMotion>动画的结束位置,但到了Chrome 65.0.3325.146中,动画结束后元素就会跳回初始位置。
问题代码示例
<svg xmlns="http://www.w3.org/2000/svg" style="padding: 100px;" > <g> <animateMotion path="M70 -48 C70 -48 136 136 230 166 M230 166 C324 196 472 370 460 470" keyPoints="0;0;0.407;1" keyTimes="0;0;0.383;1" keySplines="0.5,0.5,0.5,0.5;0.167 0.167 0.833 0.833;0.167 0.167 0.833 0.833" dur="2" fill="freeze" calcMode="spline" /> <path fill="rgba(49, 187, 174, 1)" fill-opacity="1" d=" M37,17 C37,17 12.5,40.5 39,63 C65.5,38 37,17 37,17z"></path> </g> </svg>
两种可行的解决方案
方案1:把动画直接绑定到目标<path>元素上
Chrome对容器元素(比如<g>)上的animateMotion的fill="freeze"支持有bug,把动画直接加到<path>上就能解决这个问题,Firefox也能正常兼容:
<svg xmlns="http://www.w3.org/2000/svg" style="padding: 100px;" > <path fill="rgba(49, 187, 174, 1)" fill-opacity="1" d=" M37,17 C37,17 12.5,40.5 39,63 C65.5,38 37,17 37,17z"> <animateMotion path="M70 -48 C70 -48 136 136 230 166 M230 166 C324 196 472 370 460 470" keyPoints="0;0;0.407;1" keyTimes="0;0;0.383;1" keySplines="0.5,0.5,0.5,0.5;0.167 0.167 0.833 0.833;0.167 0.167 0.833 0.833" dur="2" fill="freeze" calcMode="spline" /> </path> </svg>
方案2:用JS强制锁定结束状态
如果必须保留<g>的结构,可以监听动画结束事件,手动把元素的变换状态设置为动画结束时的状态,避免Chrome复位:
const animateEl = document.querySelector('animateMotion'); const groupEl = document.querySelector('g'); animateEl.addEventListener('endEvent', () => { // 获取动画结束时的变换矩阵 const finalTransform = groupEl.getCTM(); // 把矩阵转换为transform属性值 groupEl.setAttribute('transform', `matrix(${finalTransform.a}, ${finalTransform.b}, ${finalTransform.c}, ${finalTransform.d}, ${finalTransform.e}, ${finalTransform.f})`); // 移除动画元素,防止后续触发复位 animateEl.remove(); });
问题根源
Chrome在处理容器元素上的animateMotion动画时,fill="freeze"的效果没有正确传递给子元素,动画结束后会重置容器的变换属性。而直接将动画绑定到目标元素上,浏览器就能正确识别并保留动画结束后的最终状态。
内容的提问来源于stack exchange,提问作者喵了个咪
相关产品推荐
相关产品推荐

