konvajskonvavue-konva

Vue-Konva: Is there a way to reorder layers on the fly?


So, I've been working with vue-konva and I have something like this:

<v-container>
    <v-stage ref="stage">
        <v-layer ref="baseImage">
            <v-image>
        </v-layer>
        <v-layer ref="annotationLayer">
            <v-rect ref="eventBox">
            <v-rect ref="rubberBox">
            <v-rect ref="annotationRect">
        </v-layer>
    </v-stage>
<v-container>

Currently there are some issues if I want to draw new boxes, when there are other annotationRects already on the image. Because they are technically above the eventBox and rubberbox, they are "blocking" these two layers when the cursor is above an existing annotationRect.

But, I don't want to just constantly have eventBox and rubberBox be on top of annotationRect because I need to be able to interact with annotationRect to move them, resize them ,etc.

Is there a way for me to reorder eventBox, rubberBox, and annotationRect, i.e. changing the order to (bottom to top) annotationRect-eventBox-rubberBox from the original eventBox-rubberBox-annotationRect and back, on the fly, for example when the vue component receives an event from another component?


Solution

  • You need to define your eventBox, rubberBox, and annotationRect inside order array in the state of your app. Then you can use v-for directive to render items from the array:

    <template>
      <div>
        <v-stage ref="stage" :config="stageSize" @click="changeOrder">
          <v-layer>
            <v-text :config="{text: 'Click me to change order', fontSize: 15}"/>
            <v-rect v-for="item in items" v-bind:key="item.id" :config="item"/>
          </v-layer>
          <v-layer ref="dragLayer"></v-layer>
        </v-stage>
      </div>
    </template>
    
    <script>
    const width = window.innerWidth;
    const height = window.innerHeight;
    export default {
      data() {
        return {
          stageSize: {
            width: width,
            height: height
          },
          items: [
            { id: 1, x: 10, y: 50, width: 100, height: 100, fill: "red" },
            { id: 2, x: 50, y: 70, width: 100, height: 100, fill: "blue" }
          ]
        };
      },
      methods: {
        changeOrder() {
          const first = this.items[0];
          // remove first item:
          this.items.splice(0, 1);
          // add it to the top:
          this.items.push(first);
        }
      }
    };
    </script>
    

    DEmo: https://codesandbox.io/s/vue-konva-list-render-l70vs?file=/src/App.vue