Making a responsive canvas

Not too long ago I looked at working with HTML5 Canvas.  It’s a great little thing, and I am working on some posts to explore it more and what it can do.  However I have just ran into a problem with it which others have found, and something which is going to trip people up at some stage.  It’s not responsive.  This means that when you put your canvas work onto the web and view it on different devices, it’s not going to scale with the viewport.  Nightmare.

As I’ve been looking at canvas as part of my work, I’ve been tasked with making the canvas we use scale with the device, and even work when the screen is rotated.  Basically make it work with mobile devices.  As much as I would like to use CSS to control it all, I’ve previously found that doing things that way makes the whole canvas output blurry and generally look poor.  The only thing to do, therefore, was get the canvas to draw at specific sizes for different content areas.

The first thing to do is create the canvas you want, but instead of specifying pixels for the locations, work in percentages.  If you know that your perfect canvas is 1000 pixels wide and you want something starting 150 pixels from the left, calculate that 150 pixels as a percent.  You can then rest safe that if the canvas is half the size of the ideal, that the paths getting drawn will be half of what they were before.  They will scale.  Basically you are coding a vector image for canvas to draw.

Fonts get a little bit trickier.  You don’t always want to scale down the font size at the same rate the rest of the canvas scales.  I was fortunate enough to know what different sizes the canvas container were going to be (due to using Bootstrap to enable easy responsive coding).  This meant that when the device was small, the container for the canvas would be a certain size.  Similarly if it was medium or large, we would know the size of the container, and therefore could determine the size of the canvas.

Using the knowledge about the size of the canvas area meant I could set what the font size should be at different screen widths within an array, and use the width of the container to decide what size font should be used for that width container.  Things did get difficult when the container was col-xs-* for extra small devices, but we decided that using the same size font for anything which would be classed as “xs” was right for this particular project.  Below is an example of the array we used for determining the font size at different container widths:

var mainFontSizes = Array();
mainFontSizes[780] = '14'; // lg
mainFontSizes[683] = '12'; // md
mainFontSizes[512] = '10'; // sm

Once everything has been build using percentages for placement, distances and such like, there was only one issue remaining.  How do you code for the people who have devices which can turn?  They might go from medium to large depending on orientation, or small to medium.  Fortunately jQuery has a wonderful ability of being able to check the change in screen size, and therefore can help with that.  Simpy add a handler to the window for screen resize and then get that to call whatever functions are needed to re-draw the canvas at the right size, like so:

$(window).resize( function() { 
    // work out how large the new graph needs to be
    graphWidth = parseInt($('#main').css('width'));
    // re draw the graph
    drawGraph();
});