0

I would like to create Rectangle Shapes and Connections using the Vue-Konva/Konvajs within my application. I do not want to create load the Static values rather I would like to create the Shapes when the user clicks on the Add Node button and create Connectors when the user clicks on the Add Connector button and build the connections between Shapes.

I looked into a few things and was able to do it using the mouse events but was unable to convert it to button clicks.

Following is the current code I have: CodeSandbox

Can someone please guide me on how to create shapes and connectors on click of the button events? Any suggestion or guidance is much appreciated.

I am looking something like this: enter image description here

BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98
  • Did you see this ? https://konvajs.org/docs/vue/index.html – Vanquished Wombat Nov 05 '21 at 10:58
  • 2
    @VanquishedWombat Thanks a lot for the response. I looked at this example but the problem is that they have already created the `star shape` and then they are `dragging` it within the `stage` but in my case, I would like to create a new shape every time a user clicks on `Add Node` button. – BATMAN_2008 Nov 05 '21 at 11:03

1 Answers1

4

After trying a few things I was able to get it working. Posting here as it can be useful to someone in the future:

<template>
  <div class="container-fluid">
    <div class="row">
      <div class="col-sm-6">
        <button class="btn btn-primary btn-sm" @click="addEvent()">
          Add Event
        </button>&nbsp;
        <button class="btn btn-success btn-sm" @click="submitNodes()">
          Submit
        </button>&nbsp;
      </div>
    </div>
    <div class="row root">
      <div class="col-sm-12 body">
        <v-stage
          ref="stage"
          class="stage"
          :config="stageSize"
          @mouseup="handleMouseUp"
          @mousemove="handleMouseMove"
          @mousedown="handleMouseDown"
        >
          <v-layer ref="layer">
            <v-rect
              v-for="(rec, index) in nodeArray"
              :key="index"
              :config="{
                x: Math.min(rec.startPointX, rec.startPointX + rec.width),
                y: Math.min(rec.startPointY, rec.startPointY + rec.height),
                width: Math.abs(rec.width),
                height: Math.abs(rec.height),
                fill: 'rgb(0,0,0,0)',
                stroke: 'black',
                strokeWidth: 3,
              }"
            />
          </v-layer>
        </v-stage>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      stageSize: {
        width: null,
        height: 900
      },
      lines: [],
      isDrawing: false,
      eventFlag: false,
      nodeCounter: 0,
      nodeArray: []
    }
  },
  mounted () {
    if (process.browser && window !== undefined) {
      this.stageSize.width = window.innerWidth
      // this.stageSize.height = window.innerHeight
    }
  },
  methods: {
    handleMouseDown (event) {
      if (this.eventFlag) {
        this.isDrawing = true
        const pos = this.$refs.stage.getNode().getPointerPosition()
        const nodeInfo = this.nodeArray[this.nodeArray.length - 1]
        nodeInfo.startPointX = pos.x
        nodeInfo.startPointY = pos.y
        console.log(JSON.stringify(nodeInfo, null, 4))
      }
    },
    handleMouseUp () {
      this.isDrawing = false
      this.eventFlag = false
    },
    setNodes (element) {
      this.nodeArray = element
    },
    handleMouseMove (event) {
      if (!this.isDrawing) {
        return
      }
      // console.log(event);
      const point = this.$refs.stage.getNode().getPointerPosition()
      // Handle  rectangle part
      const curRec = this.nodeArray[this.nodeArray.length - 1]
      curRec.width = point.x - curRec.startPointX
      curRec.height = point.y - curRec.startPointY
    },
    // Function to read the Nodes after add all the nodes
    submitNodes () {
      console.log('ALL NODE INFO')
      console.log(JSON.stringify(this.nodeArray, null, 4))
      this.handleDragstart()
    },
    addEvent () {
      this.eventFlag = true
      this.setNodes([
        ...this.nodeArray,
        {
          width: 0,
          height: 0,
          draggable: true,
          name: 'Event ' + this.nodeCounter
        }
      ])
      this.nodeCounter++
    }
  }
}
</script>

<style scoped>
.root {
  --bg-color: #fff;
  --line-color-1: #D5D8DC;
  --line-color-2: #a9a9a9;
}

.body {
  height: 100vh;
  margin: 0;
}

.stage {
  height: 100%;
  background-color: var(--bg-color);
  background-image: conic-gradient(at calc(100% - 2px) calc(100% - 2px),var(--line-color-1) 270deg, #0000 0),
    conic-gradient(at calc(100% - 1px) calc(100% - 1px),var(--line-color-2) 270deg, #0000 0);
  background-size: 100px 100px, 20px 20px;
}
</style>
BATMAN_2008
  • 2,788
  • 3
  • 31
  • 98