The HTML5 standard has been around for a long time, but it seems that Canvas is not used in many places now. A very important reason is that Canvas standard has not been completely determined, so it is not suitable for large-scale production environment. However, the advantages of Canvas are also obvious. For example, when drawing diagrams containing a large number of elements, SVG is often incompetent due to performance problems. For example, IN the raffle of a technology sharing meeting I have seen, although the effect is quite dazzling, each head is DOM and animation controlled by CSS3. This results in very poor performance. In addition, with the improvement of hardware performance, video screenshots, image processing and other functions are gradually available on the web. Most websites use Flash, but Flash performance is not high on the Mac, so you need to learn some additional knowledge. Canvas uses JavaScript to draw directly and is Mac friendly, so it can be regarded as a successor to Flash.

The use of Canvas

Having said that, what exactly is Canvas?

Canvas means “Canvas” in English, but this Canvas is a new element in HTML5 that allows developers to draw a series of graphics on it. The way to write Canvas in an HTML file is simple:


Copy the code

Among them, the ID attribute can be used by all HTML elements. Canvas has only the latter two attributes (controlling width and height respectively), and nothing else. As for compatibility, CanIUse writes that the basic functionality is currently supported by 90% of browsers that users use, so it’s safe to use in most cases.

Note that it is important to use the width and height attributes of the Canvas. Do not use CSS to control the Canvas, because CSS control will cause deformation of the Canvas. Compare this to PhptpShop, which changes the “image size”, which correctly changes the “canvas size”. For example, here is a horizontal Mosaic of three images: the black box on the far left is the original image with a size of 50px by 50px; In the middle is the effect of changing the image size to 100px by 100px, the image becomes blurred, but the coordinate range for the image itself does not increase; The correct 100px by 100px Canvas is on the far right.

Most drawing methods of Canvas have nothing to do with tags and need to be operated by JavaScript, which is the so-called Canvas API.

We get this element first:

var canvas = document.getElementById('canvas');
Copy the code

We then pass a method to get an entry that can call any Canvas API:

var ctx = canvas.getContext('2d');
Copy the code

Are you excited to see 2D and think 3d? There is no 3D writing, but if you want to open the door to the 3D world, you can write Canvas.getContext (‘webgl’). However, WebGL is a standard based on OpenGL ES 2.0, which is completely different from this article, so I won’t discuss it here.

Basic concepts in Canvas

coordinates

Different from the common Cartesian coordinate system in mathematics, Canvas coordinate system is the common coordinate system in computers. It looks like this:

The top left corner of the canvas is (0,0), x increases as you go to the right, y increases as you go down, and both x and y are integers (even if they are not integers in the calculation, they will be treated as integers when drawing), in pixels.

drawing

A little bit of nostalgia. I don’t know how many of you played logo language when you were a kid. In logo language, you can control a baby turtle to walk on a board, draw, pick up a pen, and write a pen. The same goes for Canvas, where you need to control the movement and drawing of a brush. However, Canvas is more advanced. You can use some functions directly to draw the picture without having to control the position of the brush.

Basic graphics in Canvas

There are many interesting things you can do with the CTX variables defined above, but let’s first look at how to draw some basic graphs.

line

We specify that the brush moves to a certain point, and then tell the brush to go from the current point to another point. We can make the brush move, draw, and output to the screen. Examples are as follows:

ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.moveTo(10, 20);
ctx.lineTo(40, 70);
ctx.stroke();
Copy the code

In the above code, lineTo is the function used to generate the line, after which the brush moves to the end of the line. Note that the line is not displayed on the screen at this time and must be displayed by calling stroke. This makes sense, since it takes a lot of resources to output to the screen, we could have saved up a wave of lineTo and then put a big one with stroke.

The path

Drawing paths is as simple as telling CTX “I’m going to draw paths” and then drawing paths through various methods (such as lineTo). If you need to draw a closed path, give CTX a final word: “I’m done, you can close it.” Of course, don’t forget to use stroke output to the screen.

A simple example:

ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(150, 50);
ctx.lineTo(10, 50);
ctx.closePath();
ctx.stroke();
Copy the code

What if INSTEAD of just drawing path lines, I want to fill the entire path? You can change the stroke in the last line to fill, so that the contents of the closed path are filled with color just like the paint bucket in the drawing:

ctx.fill();
Copy the code

The arc/circle

The function to draw the arc has more parameters:

Arc (center of the circle x coordinates, center of the circle y coordinates, radius, start Angle, end Angle, whether it is counterclockwise);Copy the code

Notice that in the Canvas coordinate system, one side of the Angle is a straight line horizontally to the right centered at the center of the circle. The units of Angle are radians. For example, in the figure below, the center of the circle, the starting Angle (acute Angle indicated in the figure), and the ending Angle (obtuse Angle indicated in the figure) are determined, and the direction is counterclockwise, resulting in such an arc. If it’s clockwise, it’s a very, very large arc that complements it…

So if you make 2π circles, the arc becomes a circle, so you can draw circles the same way you draw arcs:

ctx.beginPath(); Ctx. arc(center x, center y, radius, 0, Math.PI * 2, true); ctx.closePath();Copy the code

The last parameter is optional (or not), because 2 PI circles are a circle, whether clockwise or counterclockwise.

rectangular

If you just want to draw a horizontal, flat, and vertical rectangle, you can use the following two methods:

// Just stroke ctx.strokeRect(top left x, top left y, width, height); // Just fill ctx.fillrect (top-left x-coordinate, top-left y-coordinate, width, height);Copy the code

Line style/Fill style

All of the previous graphics have been black, but the Canvas must be more than one color (otherwise the standard maker will get badly sprayed). In fact, Canvas can set line style and fillStyle separately, using strokeStyle and fillStyle respectively. There are three possible values: solid color, gradient, and image. Since the line style and the fill style are used in the same way, the fill style is used as an example. If you want to set the line style, simply change all fillStyle to strokeStyle, and the parameters inside remain unchanged.

Ctx.fillstyle = '#0000ff'; Ctx. fillStyle = 'rgba(64, 0, 127, 0.5)'; Var gradient = CTX. CreateLinearGradient (0, 0, 170, 0); // Set the transition color, the first parameter is the gradient position, the second parameter is the color gradient. AddColorStop (0, 'magenta'); Gradient. AddColorStop (0.5, "blue"); Gradient. AddColorStop (1.0, "red"); // set the fillStyle ctx.fillStyle = gradient; Var image = new image; image.src = '/path/to/image.png'; Var pattern = ctx.createpattern (image, 'repeat-x'); var pattern = ctx.createpattern (image, 'repeat-x'); // Set stroke padding ctx.fillStyle = pattern;Copy the code

In addition to the linear gradient mentioned in the code, there is also the createRadialGradient, which is radial gradient.

Once you’ve set the fill style, you can fill it with fill! If you set a line style, you can use stroke for stroke.

Of course, for line styles, there’s an extra method called lineWidth that you can use to control the width of the line.

The text

To draw text on a canvas, you first need to know the font and size to use:

ctx.font = '30px Verdana';
Copy the code

You can then stroke or fill the font with strokeText or fillText.

ctx.strokeText("Hello Coding!" , 23, 33); ctx.fillText("Hello Coding!" , 23, 66);Copy the code

The picture

There are three ways to draw an image on a Canvas:

CTX. DrawImage (image, x, y); CTX. DrawImage (image, x, y, width, height); DrawImage (image, sx, sy, swidth, sheight, x, y, width, height);Copy the code

The meanings of the parameters are as follows:

Swidth: optional, the width of the image to be clipped sheight: optional, the height of the image to be clipped x: Y: Y coordinates of the image to be placed on the canvas width: Optional, the width of the image to be used Height: Optional, the height of the image to be usedCopy the code

Set the canvas

If you are careful, you may notice that some of the properties are set directly to the CTX variable, such as ctx.lineWidth. If you set ctx.lineWidth, all subsequent lines will be drawn with the same width.

In fact, Canvas has many other Settings, for example, we can directly move the Canvas, rotate the Canvas, set the global drawing transparency and so on. These Settings can also be saved and restored at any time.

One thing to note is that everything that is already painted on the canvas is already fixed and will not be changed no matter what Settings you make later. This is very similar to the Windows drawing program.

No more nonsense, directly on the code:

CTX. Translate (the amount moving to the right, the amount moving down); Rotate the canvas with the center as the origin of the coordinate system ctx.rotate(clockwise rotation Angle); // Scale the canvas ctx.scale(horizontal magnification, vertical magnification) from the origin of the coordinate system; // Set the opacity of the drawing. If fillStyle is set to opacity, ctx.globalAlpha(decimal from zero to one) will be superimposed; / / set the global operations CTX. GlobalCompositeOperation = 'lighter'; // Save the current setting ctx.save(); // Restore the last saved setting ctx.restore();Copy the code

Move, rotate, and scale control the coordinate system of your drawing, and it’s great if you always have a graduated coordinate system in mind when calling these three methods.

In fact, Canvas coordinate transformation follows the knowledge of computer graphics: transformation matrix. To put it simply, a coordinate can be regarded as a matrix, and the corresponding matrix multiplied by the transformation matrix can realize the transformation of the coordinate. In order to improve the efficiency of calculation, we can first calculate the transformation matrix after the combination of several transformations, and then directly transform the current coordinate system through the transform function, or reset the coordinate system to the initial state through the setTransform function before transformation. As for the transformation matrix content, for this article is a bit beyond the outline.

Global combined operations are a bit like the “mixed options” in PhotoShop. The specific implementation method has not been completely determined yet. At present, common browsers have unified implementation methods as follows: Source-over, source-atop, destination-over, destination-out, lighter, xor. The specific behavior can be found in Mozilla’s official documentation, but since the standards are not fully established, other browsers do not guarantee that all behaviors will conform to Mozilla’s standards. Generally speaking, source-over and lighter are common, and these two standards are undisputed in the browser world.

As for saving and restoring Settings, it’s a bit more fun. First, you need to know something called the stack.

A stack is a one-dimensional array specified to operate in only one direction. The stack is empty at first, and we can push elements in this direction, and pop the last element (the top of the stack) out of this direction, but nothing else. Of course, you can’t pop more than you push, because by the time a pop hits the bottom of the stack, there are no more elements in the stack, so there’s no point in popping any more. Stacks are used for many things, such as parenthesis matching, expression evaluation, depth-first search, and even function calls in most languages.

Each time we call save, we actually push the current global Settings onto a special stack, and each time we call Restore we pop out the last saved contents and overwrite the current global Settings, so that the top of the stack is the most recently saved contents. Save and restore works very well in some cases, like when I need to draw a skewed shape and then rotate and rotate and then restore and draw other shapes.

In fact, Canvas also has many methods. For example, toDataURL directly converts the content on the current Canvas into hexadecimal data-URL, and getImageData directly converts the image into RGBA array for image processing algorithm to use. PutImageData converts RGBA arrays into images to display on canvas and so on. If combined with scheduled updates to JavaScript (preferably with requestAnimationFrame rather than setInterval), animations can occur. There are also many Canvas libraries on the Internet, which can make it easier for programmers to write their own special effects or functions based on Canvas. Here I would like to say a word: Canvas is as powerful as your imagination