Canvas scale as in DOM element scale and the scale 2d context method
So in canvas a scale could mean a few things as there is the actual canvas matrix size, then the size that the canvas is scale up or down to just like that of an image. There is also scaling an object up and down within the canvas matrix also, so the subject can get a little confusing to say the least. Still in this post I will be writing about all things canvas scale related and hopefully it will help with some of the confusion.
1 - Canvas scale
2 - Scale a canvas with in line or external CSS
Lets start with the basics here when it comes to scaling and canvas. When it comes to creating a canvas to begin with there is the actual native pixel size of the canvas, and then there is a scaled size that can be set via CSS values.
So then in this example I am creating a canvas with a native size of only 32 by 24, and then scaling it up to a size of 640 by 480 with css. The important thing to remember here is that that is the matrix size of the canvas and then the scaled up or down pixel size of the canvas. Use the canvas element with and height properties to set the size of the matrix, and then css can be used to scale that canvas just like that of an Image.
3 - Set canvas scale with canvas.style.width and canvas.style.height
So with a reference to a canvas element the width and height attributes will set the actual native size, but if you want to scale the canvas element then that should be done via the style api of the canvas element reference.
4 - The canvas scale 2d context method
There is also the scale method that can be used with via the 2d drawing context. This method is used to transform the until scale of the pixels of a canvas. So what is drawn to the canvas after the method is called will be smaller or bigger depending on the scale set with the canvas scale method, even if the values given to the method that is drawing is the same.
In this example the first rectangle drawn is one fourth the size of the canvas as expected, but the next black rectangle is one sixteenth the size of the canvas because of the unit scale that was set. This method can be used in conjunction with the canvas save and restore methods to change the unit scale, and then restore it back.
4.1 - Using ctx.scale to flip things
An interesting thing happens when passing negative values for the unit scale for the canvas scale method, doing so can be used to flip things.
5 - Canvas scale with another canvas and the drawImage 2d context method
Another thing to be aware of when it comes to scaling things with canvas is that you can use the drawImage 2d context method to draw one canvas to another canvas. The drawImage method can accept up to nine arguments that can be used to set the position and size of a source image in the canvas as well as additional arguments to set the destination position and the scaled size.
In this example I made a quick scaledDraw method that creates a new canvas and then draws to it with a given draw method. It then draws to a canvas that I give it via a toCanvas property.
6 - Scaling and translating normalized arrays of points
In this section I will be going over a simple points library that I put together that is a bunch of methods for working with an array of points.
Of course there is a scale method that accepts an array of points, and then a value that will be used to scale up those points as well as translate the points to a point of interest in the canvas matrix. However there is also a point normalization methods also that will create and array of points where each point value is a value between -0.5 and 0.5 which can be thought of as the smallest possible scale of an array of points.
So if I have an array of points I can normalize them fist, and then scale up that normalized array of points to the desired scale.
6.1 - The Points lib
So for starters lets go over the points library. the nature of the library is just a bunch of pure function style methods that accept and array of points and do things with that array of points that does not involve mutating the original array of points that was given in place.
It starts off with a scale function that takes an array of points and then just scales them all up by a scale value that is given as a second argument and then also translates with delta values also. However what if I have an array of points that is not normalized first? In other words not in the form of an array of values between 1 and 0, or -0.5 and 0.5. That makes scaling a little difficult, so it would be nice to have a method that does that first.
So in order to normalize I first need to get the max and min range values of each axis of the array of points so that I can then use that data to normalize an array of points. To do this I made two methods one of which will split an array of points into to arrays where each array is all the x values and then the other is all the y values. One I have that I can just use the Math.min and Math.max methods with the Function.apply prototype method to get my object of ranges for the points.
Once I have my get ranges method I can use that method in my normalize method when it comes to getting the ranges. Once I have the ranges I can get the delta values that I need to add or subtract for each source point in the array that will be given. I can also use these ranges to get the width and height of the points relative to that range.
The delta values and width and height can then be applied to each point in the array to create the new array or normalized points. By default I made it so the range of points is from -0.5 to 0.5, but I can also set a boolean for one of the varies to make it the 0 to 1 range also.
Then also finally have a draw method that accepts an array of points, and also a canvas context reference to draw an array of points to the canvas. I can also set the stroke and fill style and choose to not close the points when it comes to the additional arguments. There are many other ways I could go about writing this method, but for the sake of this post it will work okay.
So now that I have my points library together I can link to it from an HTML file and use it in an example that involves scaling normalized points in canvas.
6.2 - The points lib in action
Now to test out my points library. TO do so I just link to it with a script tag and, and then work out my example in-line with another script tag. Once again I just get a reference to a canvas tag, and then use my normalize and scale methods to set the desired scale for the points. I then just paint a background, and use the draw method ti draw the array of points to the canvas. Works just as expected.
This results in a square at the center of the canvas element that is 128 pixels on each size that was created from an array of points that would have been a 32 by 32 square at the upper left corner of the canvas. As I play around with the source points, and scale arguments the methods seem to work as expected.
So when it comes to canvas and scale there are a lot of topics that branch off from that, there is just scaling the canvas as in the size of it in the browser, and then there is scaling something up or down in the canvas matrix when it comes to working with logical pixels when it comes to what was covered in this section.
There is of course much more that could be added to this points library such as a method that could be used to rotate the array of points around a fixed point, as well as just about everything else that comes to mind when it comes to working out a real library that like this that has a robust set of methods. However that would be getting off topic with the theme of this post on canvas scale.
7 - Conclusion
So it would seem that the subject of canvas scale is not so simple as there is a great deal that branches off from the subject. There is increasing the actual logic pixel size, canvas matrix size, or native size if you prefer which is one way of scaling the canvas. Then there is leaving the canvas matrix size the same, and scaling up that matrix by chaining the logic pixel size. The there is of course scaling objects within the canvas when it comes to using all the arguments of the draw image method, and point normalization.