Search code examples
javascripthtmlcanvaskonvajskonva

Using Vanilla JS Canvas Methods with Konva Stage and Addressing Missing Functionality


I'm working on a web project that involves creating website like Canva. I've decided to use the Konva library for managing canvas-based graphics due to its ease of use and interactivity features. However, I have a few questions regarding the integration of vanilla JS Canvas methods within a Konva Stage and how to handle situations where Konva might lack certain functionalities.

Here's an example of what I'm currently trying to achieve, (just an example)

var canvas = new Konva.Stage({
  container: "canvas", // id of container <div>
  width: 1000,
  height: 1000,
});

const ctx = canvas.getContext("2d");

ctx.fillStyle = "green";
ctx.fillRect(10, 10, 150, 100);

In the code above, I've created a Konva Stage and then tried to use the Canvas 2D context (ctx) to draw a green rectangle on the stage. I'm aware that Konva provides its own set of methods for drawing shapes and managing interactions, but I'm wondering if it's possible to use vanilla JS Canvas methods alongside Konva in this way.

Additionally, I'm concerned about situations where Konva might lack certain functionalities that are available in the vanilla JS Canvas API. What would be the recommended approach if I encounter a scenario where Konva falls short and I need to implement a feature using vanilla JS?

Any insights, best practices, or examples? I want to ensure that I'm using Konva effectively while also being prepared to handle potential limitations.


Solution

  • There's a blog post here that gives some thoughts on selection of a lib for working with the canvas. It doesn't specifically cover your question (I will in a moment) but it has some ancillary information that you might find useful in regard to selection of a lib, and why I have found Konva a reasonable candidate.

    Question. Can I mix a canvas lib and plain JS on the same canvas?

    TLDR: Yes and no, but you won't want to.

    The NO part

    The no part relates to the fact that the canvas lib will be in charge of it's own redraw. An object-type lib, meaning Konva in the context of this question, will let you create shapes as objects - the critical part here is that the lib manages the drawing of the objects, you just ask for them to be created / positioned / etc. The lib draws them. The lib then listens for anything that might cause a redraw to be required, and does it for you. You have little control over this, and in truth you would not want it - you would be recreating the core of the lib. What that means is that if you add some lib-powered objects to the canvas, then 'manually' draw a green rect on the canvas surface using plain JS, the lib will likely clear the surface and redraw its shape objects some short time later and obliterate what you drew, so you would have to listen for that and draw your rect again. And that's not even considering the complication of z-order and where your green rect should fit in that context.

    The YES part

    I can't talk for other libs, but in the case of Konva you get to play Javascript with 'custom shapes'. A custom shape is a first class shape object in the Konva universe, but Konva expects you to provide a few things that make it custom. Key to these is the sceneFunc() which is the function inside every Konva shape that contains the canvas drawing commands. Taking that back to your example of the green rect in your question, you could create a custom shape and put the JS to show the green rect inside its sceneFunc(). Now a whole load of benefits come into view - Konva will draw your shape in the correct z-order sequence, you can use the transformer to rotate and scale / size your shape (some caveats but totally doable), your custom shape will have event listeners and be draggable without extra code. And custom shapes can be as complex in terms of canvas drawing as you need them to be. It should be clear after some thought, that a custom shape is a very very useful thing.

    Question: What if I don't want to use custom shapes?

    Answer: If mixing standard Konva shapes and your JS code 'drawing' is not required - like maybe your 'drawing' will be the background and Konva shapes the foreground - then you can layer or stack canvases one over the other. Put your 'drawing' on the lower canvas and point Konva at the top. Now there will be no interference between your canvas and Konva.

    Thoughts: I get that you need to take your time selecting a lib and you need to make a profitable choice. Have a look at that blog post I linked above as it has some pointers on how to go about making the selection. I don't really see what you are worried about in terms of what Konva might be lacking to cause you to need plain JS. If you can give an example I am sure we'll be able to give you an honest view on how to handle that with Konva. The point about using a lib is that, if it's a good one, you can focus on the use-case / business requirements of your app and not how to draw shapes in plain JS.