Home » vue » How to connect 2 objects using a line using konvajs in vuejs?

How to connect 2 objects using a line using konvajs in vuejs?

Posted by: admin November 26, 2021 Leave a comment

Questions:

Good morning, I find myself working with the Konvajs library, https://github.com/konvajs/vue-konva

There is the following documentation: https://konvajs.org/docs/sandbox/Connected_Objects.html, but I can’t implement it with vuejs

Since what I need to do is that when selecting object 1, I can drag and form the arrow and when selecting object 2, they are linked

Currently I have built the following:

<template>
    <v-container>
        <v-stage :config="configKonva">
            <v-layer>
                <v-circle :config="configCircle"></v-circle>
            </v-layer>
            <v-layer>
                <v-circle :config="configCircleA"></v-circle>
            </v-layer>
        </v-stage>
     </v-container>
</template>

<script>
    export default {
        data(){
            return {
                configKonva: {
                    width: 200,
                    height: 200
                },
                configCircle: {
                    x: 100,
                    y: 100,
                    radius: 70,
                    fill: "red",
                    stroke: "black",
                    strokeWidth: 4,
                    draggable: true
                },
                configCircleA: {
                    x: 100,
                    y: 100,
                    radius: 70,
                    fill: "green",
                    stroke: "black",
                    strokeWidth: 4,
                    draggable: true
                }
            }
        },
     }
</script>

Visually I have only created the circles, I lack the connection of these 2 through a line
enter image description here

Answers:

There are many ways to implement such functionality. Basically, you just need to listen to mousedown, mousemove and mouseup events to understand when to draw lines. You can also add touchstart, touchmove and touchend events to support mobile devices:

<template>
  <div>
    <v-stage
      ref="stage"
      :config="stageSize"
      @mousedown="handleMouseDown"
      @mouseup="handleMouseUp"
      @mousemove="handleMouseMove"
    >
      <v-layer>
        <v-line
          v-for="line in connections"
          :key="line.id"
          :config="{
            stroke: 'black',
            points: line.points
          }"
        />
        <v-circle
          v-for="target in targets"
          :key="target.id"
          :config="{
            x: target.x,
            y: target.y,
            radius: 40,
            stroke: 'black',
            fill: 'green'
          }"
        />
        <v-text :config="{ text: 'Try to drag-to-connect objects'}"/>
      </v-layer>
      <v-layer ref="dragLayer"></v-layer>
    </v-stage>
  </div>
</template>

<script>
import Konva from "konva";
const width = window.innerWidth;
const height = window.innerHeight;
let vm = {};

function generateTargets() {
  const circles = [];
  for (var i = 0; i < 10; i++) {
    circles.push({
      x: width * Math.random(),
      y: height * Math.random(),
      id: i
    });
  }
  return circles;
}

export default {
  data() {
    return {
      stageSize: {
        width: width,
        height: height
      },
      targets: generateTargets(),
      connections: [],
      drawningLine: false
    };
  },
  methods: {
    handleMouseDown(e) {
      const onCircle = e.target instanceof Konva.Circle;
      if (!onCircle) {
        return;
      }
      this.drawningLine = true;
      this.connections.push({
        id: Date.now(),
        points: [e.target.x(), e.target.y()]
      });
    },
    handleMouseMove(e) {
      if (!this.drawningLine) {
        return;
      }
      const pos = e.target.getStage().getPointerPosition();
      const lastLine = this.connections[this.connections.length - 1];
      lastLine.points = [lastLine.points[0], lastLine.points[1], pos.x, pos.y];
    },
    handleMouseUp(e) {
      const onCircle = e.target instanceof Konva.Circle;
      if (!onCircle) {
        return;
      }
      this.drawningLine = false;
      const lastLine = this.connections[this.connections.length - 1];
      lastLine.points = [
        lastLine.points[0],
        lastLine.points[1],
        e.target.x(),
        e.target.y()
      ];
    }
  }
};
</script>

DEmo: https://codesandbox.io/s/vue-konva-connection-objects-qk2ps