首页 > 解决方案 > 如何使用vue在for循环中为svg元素设置动画?

问题描述

现在正在使用 vue-konva(基于 svg 的画布库)。我正在尝试为所有由 v-loop 定义的形状设置动画。在尝试使用 Konva Animation 库函数时,我收到“无法读取未定义的属性 'getNode'”错误。我假设这是因为 ref 必须具有一个特定元素并且不能在 v-for 循环内进行寻址。如何同时为所有多边形设置动画?

SVG / 画布元素:

<v-regular-polygon
  v-for="el in results"
  ref="hexagon"
  :key="el.index"
  :config="{
    x: 200 * Math.abs(el.land),
    y: 200,
    sides: 6,
    radius: 20,
    fill: 'red',
    stroke: 'black',
    strokeWidth: 4,
  }"
/>

负责动画的函数

mounted() {
  this.fetchTemperature()
  const vm = this
  const amplitude = 100
  const period = 5000
  // in ms
  const centerX = vm.$refs.stage.getNode().getWidth() / 2

  const hexagon = this.$refs.hexagon.getNode()

  // example of Konva.Animation
  const anim = new Konva.Animation(function (frame) {
    hexagon.setX(amplitude * Math.sin((frame.time * 2 * Math.PI) / period) + centerX)
  }, hexagon.getLayer())

  anim.start()
},

标签: vue.jsanimationsvgnuxt.jskonva

解决方案


您可以通过添加索引为每个多边形设置唯一的参考。

<v-regular-polygon
          v-for="(el, i) in results"
          :ref="`hexagon_${i}`"
...

这是一个例子:

<template>
  <div id="app">
    <v-stage :config="configKonva">
      <v-layer>
        <v-circle
          v-for="(item, i) in items"
          :config="item"
          :key="i"
          :ref="`circle_${i}`"
        ></v-circle>
      </v-layer>
    </v-stage>
  </div>
</template>

<script>
import Konva from "konva";

export default {
  name: "App",
  data() {
    return {
      items: [
        {
          x: 30,
          y: 100,
          radius: 20,
          fill: "red",
          stroke: "black",
          strokeWidth: 2,
        },
        {
          x: 100,
          y: 100,
          radius: 20,
          fill: "red",
          stroke: "black",
          strokeWidth: 2,
        },
      ],
      configKonva: {
        width: 200,
        height: 200,
      },
    };
  },
  mounted() {
    for (let i = 0; i < this.items.length; i++) {
      const node = this.$refs[`circle_${i}`][0].getNode();
      const period = 1000;
      const amplitude = 10;
      const anim = new Konva.Animation((frame) => {
        node.setX(
          amplitude * Math.sin((frame.time * 2 * Math.PI) / period) +
            this.items[i].x
        );
      }, node.getLayer());

      anim.start();
    }
  },
};
</script>

代码沙盒


推荐阅读