Encountering issue with Konva/Vue-Konva: receiving a TypeError at client.js line 227 stating that Konva.Layer is not a

I am integrating Konva/Vue-Konva into my Nuxtjs project to create a drawing feature where users can freely draw rectangles on the canvas by clicking the Add Node button.

However, I encountered an error:

client.js:227 TypeError: Konva.Layer is not a constructor
    at VueComponent.addNode (index.js?!./node_modules/vue-loader/lib/index.js?!./pages/Test1.vue?vue&type=script&lang=js&:65)

The goal is to allow users to draw rectangular shapes on the Konva Canvas when they click the Add Node button.

Below is a snippet of my code:

<template>
  <div>
    <button class="btn btn-primary btn-sm" @click="addNode()">
      Add Node
    </button>&nbsp;
    <div id="container" ref="container" />
  </div>
</template>

<script>
import Vue from 'vue'
let Konva = null

export default {
  data () {
    return {
    }
  },
  async mounted () {
    if (process.browser) {
      const VueKonva = await import('vue-konva')
      Konva = await import('konva')
      Vue.use(VueKonva)
      Vue.use(Konva)
    }
  },
  methods: {
    // Function to draw nodes/shapes on the canvas when the Add Node button is clicked
    addNode () {
      const layer = new Konva.Layer()
      const stage = this.$refs.stage.getStage()
      const rect1 = new Konva.Rect({
        x: 20,
        y: 20,
        width: 100,
        height: 50,
        fill: 'green',
        stroke: 'black',
        strokeWidth: 4
      })
      layer.add(rect1)
      stage.add(layer)
      stage.draw()
    }
  }
}
</script>

Answer №1

<template>
  <div class="container-fluid">
    <div class="row">
      <div class="col-sm-6">
        <button class="btn btn-primary btn-sm" @click="addEvent()">
          Include New Event
        </button>&nbsp;
        <button class="btn btn-success btn-sm" @click="submitNodes()">
          Submit Data
        </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: 'New 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to Calculate Dates in Javascript

Currently exploring the realm of JavaScript, I find myself in the process of developing a dashboard for an e-commerce platform that I am currently involved with. My goal is to display data for all dates starting from the date of the initial order placed. M ...

Is it possible to merge node modules that have similar functionalities?

When utilizing node.js, you may encounter module dependencies containing functions with similar functionalities, such as underscore, lodash, and lazy (potentially in different versions). Is there a way to specify which module from a group of similar metho ...

Is the PHP Ajax parameter missing during the upload process?

I'm attempting to do a simple upload, but I seem to be struggling. It could be that I'm not understanding it properly, or perhaps it's just too late at night for me to figure it out. After doing some research, I came across this example on ...

"When running next build, NextJS fetch() function throws an error indicating an invalid URL, but everything works fine when using

Currently, I am in the process of developing a NextJS React application and attempting to retrieve data from my server by using the following line of code: let data = await fetch('/api/getAllAlumniInfoList').then(res => res.json()) Interestin ...

Uninstall webpack-dev-server version 1.14.1 and replace it with version 1.14.0

Can someone help me with the process of uninstalling webpack-dev-server 1.14.1 and installing version 1.14.0 on Ubuntu using just commands? Error message: Uncaught TypeError: Cannot read property 'replace' of null at eval (eval at globalEval (jq ...

Vue.js tutorial: Adding a question mark to the URL when submitting a login form

There have been some strange issues with my login form recently. It initially directs me to However, when I try to log in, instead of logging me in, it redirects me to: I can only successfully log in after clicking on the login button again. What could ...

Extract several "documents" from one compilation

To easily convert my code into a single module using webpack, I can use the following method: { entry: path.join(__dirname, 'src/index.js'), output: { path: path.join(__dirname, 'dist'), filename: 'bundle.js', ...

What could be causing the "Uncaught SyntaxError" when the "import vue" line is used?

Every time I start a new Vue application, I encounter this error in the console: Uncaught SyntaxError: Unexpected identifier appearing at main.js:1 This error shows up even before I begin coding. I'm puzzled about what might be wrong with my import ...

When using form.serialize() in Django forms, an empty object is being sent

Upon clicking the button, my AJAX request is sending an empty object Object { } instead of form data. The form on my page consists of checkboxes and its HTML structure is as follows: <form method="post" action="" data-id="filter-form"> //Included ...

Are you in need of a JavaScript data validation tool?

Trying to find a library that can validate input in a specific format, such as: { points: array of { x: positive and less than 20, y: positive and less than 15 } } Ideally, it should work on both server and client sides and either return a boolean or th ...

Use jQuery to set a Firebase image as the background of a div element

Is there a way to fetch an image from Firebase and use it as the background for a div element? I've tried several approaches without success. Could someone share some examples on how to achieve this? <div class="museBGSize rounded-corners grpelem" ...

Update tailwindcss color dynamically according to user input within Vue3/Nuxt3

I am currently exploring a method to allow users to specify the primary color of a website. When defining my Tailwind classes, I aim to utilize something like bg-primary-600 instead of directly inputting a color. This way, if the value for primary changes, ...

Scraping the web with cheerio: Should we delete or disregard a child element?

There's a specific website I'm looking to scrape, and its structure is as follows: <p><strong>a certain heading:</strong> some information etc. blabla </p> <p><strong>another heading:</strong> more deta ...

Setting line chart data for Chart.js

Can you help me troubleshoot an issue I'm facing with creating a dataset for a line chart in Chart.js? Despite having an array of objects, the dataset isn't rendering correctly and I end up with two line charts instead of one. What could be causi ...

What is the best way to prevent a directory containing mock files from being included in a webpack build using vue.config.js?

In the root directory, I have a folder named mock that contains mock data used for running the app in development mode. However, when I build the app for production using vue-cli-service build, this folder gets included in the bundle, which increases the s ...

Exploring External Functions in Angular Beyond the Library

Transitioning from standard JavaScript to Angular has been a bit challenging for me, especially when working with the Google Places library (or any other asynchronous callback). Here is the code snippet: var sparkApp = angular.module('sparkApp' ...

Importing D3 data from CSV files using the "%" symbol

I am trying to import a CSV file with the following data: Month, Ratio January, 0.19% February, 0.19% March, 0.19% April, 0.18% The current code snippet I'm using is as follows: d3.csv("month_ct.csv", function(d) { return { month: d ...

Encountering event binding errors with Vue application connected to Netlify form

My goal is to hide/show a div based on the value of a form input. I was able to achieve this successfully with a standard form, but when I tried implementing it using netlify-forms, I encountered the following error: Unhandled promise rejection TypeError: ...

I'm confused as to why the icon color isn't changing on the Blogger homepage for each individual user

I'm experimenting with changing the eye color based on visitor count. It works perfectly fine on static posts in my Blogger, but it fails to update the eye color properly on my homepage according to the set numeric values. Instead of displaying differ ...

Tips for using jQuery to create a delete functionality with a select element

I'm relatively new to utilizing jquery. I decided to tackle this project for enjoyment: http://jsbin.com/pevateli/2/ My goal is to allow users to input items, add them to a list, and then have the option to select and delete them by clicking on the t ...