如何在Vue中使用v-for循环实现svg元素动画并解决vue-konva的getNode报错
问题原因
Vue 中在 v-for 循环内给元素绑定相同 ref 时,$refs.xxx 会自动生成一个包含所有对应组件实例的数组,而非单个实例。你之前直接对数组调用 .getNode() 方法,数组本身没有这个方法,所以才会抛出 Cannot read property 'getNode' of undefined 报错。
解决方案
你不需要修改模板代码,只需要调整动画初始化的逻辑,遍历 ref 数组获取所有多边形节点即可。
修改后的JS代码
mounted() { this.fetchTemperature() const amplitude = 100 const period = 5000 const centerX = this.$refs.stage.getNode().getWidth() / 2 // 兼容空数据场景,避免报错 if (!this.$refs.hexagon || !Array.isArray(this.$refs.hexagon)) return // 批量获取所有多边形的Konva节点实例 const hexNodes = this.$refs.hexagon.map(item => item.getNode()) if (hexNodes.length === 0) return // 单个动画实例批量处理所有节点,性能更好 this.anim = new Konva.Animation((frame) => { const baseOffset = amplitude * Math.sin((frame.time * 2 * Math.PI) / period) + centerX hexNodes.forEach((node, index) => { // 如果需要不同节点有不同动画效果,可以在这里基于index自定义偏移量 node.setX(baseOffset) }) }, hexNodes[0].getLayer()) this.anim.start() }, // 组件销毁时停止动画,避免内存泄漏 beforeUnmount() { this.anim?.stop() }
可选:每个多边形独立动画
如果需要不同多边形有不同的动画参数(比如不同周期、振幅),可以遍历创建独立的动画实例:
hexNodes.forEach((node, index) => { // 每个节点的周期随index递增,形成错落的动画效果 const customPeriod = period + index * 300 const anim = new Konva.Animation((frame) => { const offsetX = amplitude * Math.sin((frame.time * 2 * Math.PI) / customPeriod) + centerX node.setX(offsetX) }, node.getLayer()) anim.start() })
注意事项
- 如果你的
results数组是fetchTemperature接口异步返回的,不能直接在mounted里执行动画初始化,需要在接口拿到结果、给results赋值后,调用this.$nextTick()再执行动画逻辑,否则$refs.hexagon会是空数组。 - 所有多边形如果不在同一个图层,需要把所有关联的图层都传入
Konva.Animation的第二个参数数组中。
内容的提问来源于stack exchange,提问作者neverhalfnot
相关产品推荐
相关产品推荐

