You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 20:15:10