Konva – no automatic scrollbars – what?

After getting a few shapes onto the canvas, folks start wondering about how to make the canvas play nice with their UI and the subject of scrollbars emerges. Here are some thoughts on that…

Let’s get the bad news out of the way:

There are no automatic scrollbars on a canvas element!

Yep, pretty shocking. Never fear, there are ways to get scrollbars to play – read on for the full discussion or for TLDR see the code at CodePen.

Before we dive in though, a quick point on the stage creation method. When we use the following, what effect do the height and width have?

Const stage = new Konva.Stage({
    width: 800,
    height: 600,
    container: "container",
    . . . 
})

To answer this we need to look at the HTML structure that we get.

<div id="container">
    <div class="konvajs-content" role="presentation" style="position: relative; user-select: none; width: 800px; height: 600px;">
        <canvas width="800" height="600" style="padding: 0px; margin: 0px; border: 0px; background: transparent; position: absolute; top: 0px; left: 0px; width: 800px; height: 600px; display: block;">
        </canvas>
    </div>
</div>

As we can see, the container div – which was the only part of this that existed before we asked for a new stage – now has a #konvajs-content div within it, and nested inside of that we have the HTML5 canvas element. Both of those have the width and height from our new stage request.

Conclusion – the dimensions set in the new Stage request are used to configure the dimensions of the HTML elements.

Does this limit the area on the stage that I can add shapes? No.

Does this limit the position that I can move the stage to via stage.position()? No.

Is there a limit to the stage area – yes but it’s a grey area because this limitation is about how much memory browser providers are willing to allow the canvas to have. Safari complains if you go larger the 4097 x 4096 pixels. For Google Chrome, the maximum allowable width and height are 32,767 pixels and the maximum allowable area is 268,435,456 pixels, and for Firefox, the maximum allowable width and height are 32,767 pixels and the maximum allowable area is 472,907,776 pixels.

So, yes, there are limits.

Within these limits, you can consider that the width and height that you pass in the new Stage request have no impact on the area you can place shapes or translate (aka move) layers or the stage to.

Are there any concerns about large canvases?

As a rule of thumb it is best to assume that handling more data, rather than less, is leading toward performance issues. You wouldn’t send a huge image to a web page – you would think about optimizing its size to match the purpose. In the same way, you should think about the impact of creating a large canvas element because we can assume that a large canvas will have similar handling costs in the browser to a large image. Very unscientific, but we might as well help ourselves and setout to avoid problems!

So what does that mean in practice?

Well, going back to the subject of this article, this means that we should aim to keep our canvas element a sensible size – ideally exactly the size that we want to use to display our diagram / stage in the browser UI.

Which is fine if the stage fits inside the canvas.

But not so good when we zoom in on the stage and start losing some of the detail on the edge as they get clipped out of view. At this point we start thinking about the usual solution in the form of scroll bars, and maybe we reach for Google and start researching scroll bars on the canvas element.

But wait – there are no automatic scrollbars on a canvas element! Boo.

So how an we overcome this annoyance?

The Konva website has a number of approaches which are all feasible and usable. I’ll add a quick summary here to save you diving off but do go to the link for the full explanation.

1 – just use a large canvas – this will give you scrollbars if the surrounding div element has overflow set. The down side is that large canvases, like large images, are slow. Actually large canvases are slower than large static images because they inherently involve more work per refresh than static images. Conclusion – workable but not optimum.

2 – User stage dragging – this option has you ignoring scroll bars and using click-drag UX to let the user pan the stage around. The effect is the same and it might work for you, or your boss who grew up with Windows 95 will probably insist on scroll bars anyway! On the plus side, it’s very little extra work if you can stick with only this approach, so its worth standing your ground.

3 – Emulate scrollbars – literally DIY your own scrollbars in the canvas. I would avoid this because of the overhead and all the nuances of writing scrollbar logic. Plus the look & feel is going to instantly mark this out as non-standard and the boss’ll have you forever fettling it. Don’t do it!

 4 – Emulate screen moving with transform – this is my preference. For the expense of a couple of extra divs and some simple CSS, we get native browser scrollbars and good performance. In a nutshell, we have an outer div that will display the scrollbars, then an inner div that we make the same size that is needed to display the entire stage contents. The canvas and outer div remain the same size as is perfect for your UI, and never change size. To emulate panning the stage, we move the stage position in harmony with the scroll bar movements. Read that again – it’s important – we don’t change the canvas size, we move the stage on the canvas surface! It works like a charm and is memory optimized. Yes, we do have a potentially large empty inner div but then browsers are good at that type of thing! You might have seen this technique done with plain HTML image viewers where it is a common technique.

Summary

We’ve seen that the initial size that we use to create the stage is put to work preparing the page elements, but has no limiting effect on the useable co-ordinates of of the stage. We’ve looked at the fact the the canvas element does not have built-in scrollbars, and we’ve looked at some options to provide them, and there’s some code to take away and play with for what I consider the optimum option.

Thanks for reading

VW. April 2023

Photo by James Kemp at Unsplash

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: