If you know about Stage.draw() and that you don’t need to worry about it any more, don’t read this – put your feet up and have some cake. If you are at all fuzzy on the subject, read on…
What is Draw all about?
Ok – Konva is a wrapper for the HTML5 canvas. In essence, Konva gives you an object model through which you can make up shapes and movements. But these all have to be drawn onto the canvas itself before we can see anything. This is what draw() is about.
Way back in the early days of canvas, before everything got so fast, we used to have to worry about how quickly the canvas could draw our stuff out. We used to have to take care NOT to ask for a Konva stage.draw() on every little change. For example, if we were moving 10 shapes we would move them all then call for a single draw.
Then came stage.batchDraw() which was harmonised with the requestAnimationFrame() process of the browser. Think of it like this, your device has a lot of stuff to do, so when you ask for a draw() its not just sitting there waiting for that call. Oh no, its off checking your email, playing your favorite Katy Perry track on Spotify, or digging out another BitCoin. It will get around to doing it, kind-a like a teenager will get round to cleaning their room, meaning when they are good and ready!
The requestAnimationFrame() thing harmonises your drawing with the point that the browser has time to spare to do it. [Aside: this is the whole reason why you should be interested in the frame time argument of the Konva.Animation function – because only inside the function do you get to know the time that the frame is executing meaning that only then can you compute how far along the animation journey or change you are at that precise point in time].
So – batchDraw() started to utilize the animationFrame capability of the browser. Under the covers it queued up the draw output for the next pass of the animationFrame. Good, it gave smoother redraws, but we still had to remember to call it.
Then @Anton spotted that since there are only 3 actions that mean we need to redraw (shape create, erase, and setAttrs) he could automatically trigger a batchDraw() call on each of those actions.
And added the Konva.autoDrawEnabled switch, which is defaulted to ‘true’. Released in Konva@8.
Which is amazingly fabulous because I don’t have to scratch my head over why there seems to be a bug when I made a change to add a new shape to the stage but I can’t see it. [Meaning all those times I forgot to ask for a redraw – but we don’t need that now!]
So you can stop diligently coding you stage or layer draw or batchDraw calls.
Totally. No longer needed. Stop it! Konva does all the optimised draw calls for you.
Would I ever want to turn this off?
Good question. I think maybe yes, but then you would turn it on again very soon after. The use-case I am thinking of is where you need to restrict a shape’s drag location in the shape.onTransform() event.
What – ok, when you drag a shape you have 2 ways to intervene with where the shape lands. The crux is when those functions are fired. The dragBoundFunc is how it should be done, because it is executed BEFORE the shape is moved. Meanwhile you can be lazy and check the new position in the Shape.onTransform(). In most cases you can decide to move the shape somewhere else if you don’t like where it went to.
But importantly onTransform() is executed AFTER the shape position (and/or other attrs) is updated.
What that means is, if you use onTransform() to keep a shape in some particular area, when the user ‘throws’ the mouse across the desk, you might get a janky effect where the shape appears to have escaped and jumps back quickly to where it should be.
In this case you might want to set Konva.autoDrawEnabled(false) at the top of your onTransform() and switch it back to true at the end. In this way you will not see the janky flicker because you will have put the shape back into its target area before Konva draws it.
What you should really do, of course, is use the dragBoundFunc then you won’t have to mess with Stage.autoDrawEnabled, but I had to make up some reasonable use case to help me explain.
We’ve looked at why Konva ever had a Stage.draw() method, explored why it is now no longer needed, and we’ve looked at (a dodgy) use case for temporarily disabling Stage.autoDrawEnabled.
By the way, you might see references to Stage.draw() or batchDraw() in the Konva docs, my blogs or other online materials. The docs will eventually catch up but those older pieces if internet kruft will be there unchanged, forever.
Thanks for reading.
VW March 2023
Photo by Rob Martin on Unsplash