Reputation: 41
I have an application that draws over 260 plots on a canvas. The decision to put them on a single canvas was dictated by speed considerations - its much faster that way for various tasks (such as zooming and panning). I.e., splitting to 260 canvases is not an option in this case.
Everything works perfectly fine on Opera, Firefox and IE. Chrome, however, stops displaying the canvas when the height becomes larger than ~8130 pixels (the width is constant - 834 px).
I.e. I have the ability to add/remove charts on fly (they are stacked one upon another), and once the height exceeds 8130 px Chrome simply "hides" the canvas. It remains responsive and no error is thrown - what could be the reason?
Upvotes: 4
Views: 2218
Reputation:
Although the standard specify a unsigned long size for the canvas:
interface HTMLCanvasElement : HTMLElement {
attribute unsigned long width;
attribute unsigned long height;
Source: WhatWG/Canvas element
most browsers seem to limit the size to 8192 (Safari apparently to 6826).
In any case (generally speaking) -
If you need a canvas size bigger than that I would say you should definitely re-think the design. Canvas should rarely need to be bigger than what you can actually see on the screen. Consider the canvas as a view-port to your data not the holder of it. This is how most operating systems works as well (at low-level) as this has proven to be the best approach over the decades.
Consider the band-width requirements (not completely accurate as this is based on implementation and its optimizations - but for the sake of a pointer to what we're dealing with):
A canvas size of 8192 x 8192 pixels using RGBA buffer consumes 256 MB raw memory (and depending on browser implementation it could be the double).
Update that @ 60Hz and band-width is minimum 15 GB/second. In addition other browser and system content adds to this. If this is used at a typical consumer computer (and not on a developer machine) the theoretical benefit is easily lost.
Yes, you can gain speed by pre-render a large area and move that into view-port by simply blitting the pixels from that to the visible one - up to a certain point and a certain cost (memory being one factor). Some of the speed gain is anyway lost by using JavaScript to move the "blitting source" around compared to more low-level environments where this gain is more significant.
It's in general better to keep your data in a vector format (array/typed array/object) and plot the visual portion of by checking boundaries, ie. what data would be visible in the view-port. You can optimize the data in various ways to access it fast (see for instance quad-trees).
Render the vector data is not so costly as one might think (if done "correctly") and the smaller the canvas is the faster it is to clear it and redraw the data.
The main trick however is to blit content that is already on the canvas (same effect as blitting from a huge canvas) and only update the new gaps.
My 2 cents..
Upvotes: 5