1

I need to draw a dynamically-generated diagram onto the page and have thus far been using a canvas element. Unfortunately, some users have diagrams so large that the resulting canvas exceeds the size limitations of mobile browsers - the result is an empty canvas.

I have tried drawing onto smaller tiled canvasses, but this is inefficient as the drawing needs to be done multiple times.

I've also tried creating a single large canvas in memory and then using drawImage to slice it up onto smaller tiled canvasses. This fails because the in-memory canvas exceeds maximum canvas size (even though it has not been appended to the DOM).

I'm looking for any suggestions on how to get a large dynamic diagram drawn onto the page when it's width/height aren't known in advance.

Thanks!

Fijjit
  • 1,399
  • 2
  • 17
  • 31
  • a slightly related question however in the comments it seems there are some suggestions and a github repo to someone trying to get around the limitations [SO question here](http://stackoverflow.com/questions/6081483/maximum-size-of-a-canvas-element) – atmd Jan 30 '15 at 13:33
  • 1
    *Very Important* -- Stop & Redesign using a smaller canvas--between 1-2 times the target display size. If you are trying to use the max size of canvas then your app will render slowly and consume massive memory. That's because render time is proportional to canvas size--bigger==slower. And memory consumption is proportional to 4X canvas size. An html canvas sized to maximum simply will not run on a low-resourced device like mobile. You give no specs on your app, so we can't help you redesign. But again...Warning...You're going down a dead end! – markE Jan 30 '15 at 15:29
  • 1
    @Roger. OK, it's likely that you have a valid suggestion, but you really must give the questioner your logic behind your suggestion. ;-) – markE Jan 30 '15 at 15:35
  • Thanks @markE - you're right of course and - in the end - none of the options we've come up with make canvas a viable solution for us. We've gone down the SVG route instead and it's proven a much more suitable technology. – Fijjit Jan 30 '15 at 19:54
  • @Roger, you were the inspiration for us revisiting SVG, so if you want to turn your comment into a question I'd be happy to mark it as correct. – Fijjit Jan 30 '15 at 20:04
  • @markE Ok, I put an answer. – Roger Feb 03 '15 at 14:51

2 Answers2

2

Pay a visit to SVG it seems to be well supported

You may want to use svg instead because you get rendering for free, so, scrolling and zooming should not be a problem as opposed to a canvas where you have to do pretty much everything yourself.

Roger
  • 2,912
  • 2
  • 31
  • 39
  • I'll add that auto-scaling for retina is a big bonus, plus it seems to be much better supported than canvas in Android and especially webviews in Android. – Fijjit Feb 06 '15 at 21:32
  • Do NOT use SVG for large, complex vertex drawings, however. https://oreillymedia.github.io/Using_SVG/extras/ch08-precision.html – Andrew Nov 04 '19 at 17:02
1

You should use the concept of 'virtual resolution', to split the issue into two simpler ones :
- What will be my canvas size ?
- What will be my diagram size ?

Then you can use the transforms (scale) to ensure your diagram fits on your canvas.
A secondary benefit is that implementing zoom/panning will be simple once you have the virtual resolution logic.

Just a few lines of code to clarify :

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var diagramWidth = ... 
var diagramHeight = ...
var aspectRatio = Math.min( canvas.width/diagramWidth, canvas.height/diagramHeight);
context.scale(aspectRatio, aspectRatio);
// ... now you can draw in the diagram space.
// So to draw a point in the middle of the canvas write: 
context.fillRect(diagramWidth/2, diagramHeight/2, 1, 1); 
GameAlchemist
  • 18,995
  • 7
  • 36
  • 59
  • Thanks for the suggestion. It's a good technique for shrinking the diagram down to fit, but unfortunately I need it to be displayed full size. I considered using a window-sized canvas and re-drawing its contents when the user scrolls, but this would have performance problems and iOS doesn't repaint when scrolling, so very messy. – Fijjit Jan 30 '15 at 19:51
  • 'I need it to be displayed full size' : I don't know how to emphasize it enough but there's absolutely no point in using a canvas for display that has a size that is even 1 physical pixel wider/taller than the actual display width/heigth. So IF you need to somehow provide a .png file that is 5000X5000 px : that is another problem. Are you sure the image viewers will have the display that fits ? Most likely the display will be done using a sad downscaling algorithm. A canvas is designed to be displayed, not printed, it seems. – GameAlchemist Jan 31 '15 at 12:30