Как анимировать элементы svg в цикле for с помощью vue?

#vue.js #animation #svg #nuxt.js #konva

Вопрос:

работа с vue-konva (библиотека холстов на основе svg) прямо сейчас. Я пытаюсь анимировать все фигуры, которые определяются v-образным контуром. При попытке использовать функции библиотеки анимации Konva я получаю ошибку «Не удается прочитать свойство ‘getNode’ неопределенного». Я предполагаю, что это связано с тем фактом, что ссылка должна содержать один конкретный элемент и не должна быть адресована внутри цикла 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()
},
 

Ответ №1:

Вы можете задать уникальную ссылку для каждого полигона, добавив индекс.

 <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>
 

Codesandbox

Комментарии:

1. Большое спасибо! Попробовал, но я получаю ту же ошибку. По вашему предложению, должен ли я изменить ссылку в методе анимации? Внутри здесь: const hexagon = this.$refs.hexagon.getNode() Учитывая, что новая ссылка :ref=» hexagon_${i} »

2. Конечно, вам также следует изменить метод получения ссылок, например const hexagon = this.$refs[ , hexagon_${i} ].getNode() , где i находится индекс в вашем цикле в массиве полигонов.

3. Можете ли вы привести мне пример? Если я хочу «массово» анимировать все шестиугольники сразу, то все они должны иметь одинаковую анимацию. Танки!

4. Я добавил пример с парой кругов, анимированных с помощью фреймворка Konva