如何使用JS Element.animate()实现SVG连接线随移动矩形同步动画
问题原因
- SVG坐标类属性(x、y、x1、y1、x2、y2等)默认使用viewBox下的无单位用户坐标,你在动画关键帧里给值加了
px单位,导致Web Animations API无法正确识别属性值类型,因此线条没有触发动画。 - 如果矩形的最终位置是运行时动态计算的,预先写死线条的关键帧会不够灵活,更推荐逐帧同步端点坐标的方案。
直接修复原有代码
去掉关键帧里的px单位即可,可额外添加fill: 'forwards'让元素动画结束后停在最终位置:
<svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 700 360" id="theSVG"> </svg>
let svg = document.querySelector("#theSVG"); const SVGNS = "http://www.w3.org/2000/svg"; function drawing() { let rect = document.createElementNS(SVGNS, "rect"); rect.setAttribute("x", 100); rect.setAttribute("y", 100); rect.setAttribute("width", 100); rect.setAttribute("height", 100); rect.setAttribute("stroke", "black"); svg.appendChild(rect); let rect2 = document.createElementNS(SVGNS, "rect"); rect2.setAttribute("x", 10); rect2.setAttribute("y", 10); rect2.setAttribute("width", 50); rect2.setAttribute("height", 25); rect2.setAttribute("stroke", "black"); svg.appendChild(rect2); let line = document.createElementNS(SVGNS, "line"); line.setAttribute("x1", rect.x.baseVal.value); line.setAttribute("x2", rect2.x.baseVal.value); line.setAttribute("y1", rect.y.baseVal.value); line.setAttribute("y2", rect2.y.baseVal.value); line.setAttribute("stroke", "darkgray"); svg.appendChild(line); rect.animate([{ x: rect.x.baseVal.value }, { x: 200 }], { duration: 5000, iterations: 1, fill: 'forwards' }); rect2.animate([{ y: rect2.y.baseVal.value }, { y: 300 }], { duration: 5000, iterations: 1, fill: 'forwards' }); line.animate([{ x1: line.x1.baseVal.value, y2: line.y2.baseVal.value }, { x1: 200, y2: 300 }], { duration: 5000, iterations: 1, fill: 'forwards' }); } drawing();
动态同步方案(适合矩形位置运行时计算的场景)
不需要预先给线条写关键帧,通过requestAnimationFrame逐帧读取矩形的当前动画位置,同步给线条端点即可,不管矩形后续运动逻辑怎么改,线条都会自动跟上:
// 接上面的drawing函数,把原来的line.animate部分替换成下面的代码 function syncLine() { line.setAttribute('x1', rect.x.baseVal.value); line.setAttribute('y1', rect.y.baseVal.value); line.setAttribute('x2', rect2.x.baseVal.value); line.setAttribute('y2', rect2.y.baseVal.value); requestAnimationFrame(syncLine); } syncLine();
path/polyline实现说明
- 使用
<polyline>时直接对points属性做动画,值为空格分隔的坐标对,不需要加单位,两个关键帧的坐标点数量要一致才能平滑过渡:
polyline.animate([ {points: "100 100 10 10"}, {points: "200 100 10 300"} ], { duration: 5000, fill: 'forwards' })
- 使用
<path>时直接对d属性做动画,同样要求两个关键帧的路径结构完全一致,仅坐标值不同:
path.animate([ {d: "M 100 100 L 10 10"}, {d: "M 200 100 L 10 300"} ], { duration: 5000, fill: 'forwards' })
内容的提问来源于stack exchange,提问作者jzoe
相关产品推荐
相关产品推荐

