0

working with vue-konva (svg based canvas library) right now. I'm trying to animate all shapes which are defined by a v-loop. While trying to use the Konva Animation library functions, I'm getting "Cannot read property 'getNode' of undefined" error. I'm assuming this is due to the fact that a ref has to have one specific element and not be adressed inside a v-for loop. How can I simultaneaously animate all the polygons?

SVG / canvas element:

<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,
  }"
/>

function responsible for animation

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()
},
kissu
  • 40,416
  • 14
  • 65
  • 133

1 Answers1

0

You can set a unique ref to every polygon by adding an index.

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

Here's an example:

<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

Eugene Karataev
  • 1,777
  • 1
  • 11
  • 24
  • Thanks a lot! Tried it out, I'm getting the same error though. By your suggestion, do I have to change the reference in the animation method? Within here: const hexagon = this.$refs.hexagon.getNode() Considering the new ref is :ref="`hexagon_${i}`" – neverhalfnot May 26 '21 at 07:27
  • Sure, you should change the ref getter too like `const hexagon = this.$refs[`hexagon_${i}`].getNode()`, where `i` is the index in your loop on polygons array. – Eugene Karataev May 26 '21 at 07:37
  • Can you give me an example? If I want to "mass" animate all hexagons at once, so they should all have the same animation. Tanks! – neverhalfnot May 26 '21 at 22:53
  • I added an example with couple of circles animated with Konva framework – Eugene Karataev May 27 '21 at 07:29