introduce

SVG builds XML trees to draw graphics, while Canvas draws graphics by calling related methods. Difference: SVG draws graphics by removing or changing the DOM method while using Canvas requires the image to be erased. The drawing API is defined in the drawing context. It’s not defined in the canvas. To get a context object, you need to call the canvas’s getContext method to get the context of the painting.

The canvas element and context belong to two different objects, where the canvas element is the Canvas canvas and the context object is the context required for drawing.

For 3D graphics, that is, webGL encapsulates the basic OPENGL. When webGL is called, its browser will call the OPengL-related API

Draw the circle

<! DOCTYPE html> <html lang="zh_CN" xmlns="http://www.w3.org/1999/html">
<head>
    <meta charset="UTF-8"> <title> title </title> </head> <body> <div> The first garden </br> <canvas ID ="square" width="10" height="100"> </canvas> </div> <div> The second garden <canvas id="circle" width="10" height="10">
    </canvas>
</div>
<script src="./js/index.js" charset="UTF-8"></script>
</body>
</html>
Copy the code
// Get the canvas elementlet canvas = document.getElementById("square"); // Get the context for drawing a 2D elementlet context = canvas.getContext("2d"); // Set the fill color to red context.fillstyle ="#f00"; // fill a square context.fillrect (10,0,10,10);Copy the code

Draw line segments and fill polygons

// Get the canvas elementlet canvas = document.getElementById("square"); // Get the context for drawing a 2D elementlet context = canvas.getContext("2d"); // Start a path context.beginPath(); // Define a new subpath from 100,100 context.moveto (100,100); // Draw a line from 100 100 to 200 200 context.lineTo(200,200); // Draw a line segment context.lineTo(100,200); // Draw a path from 100 200 to 100 100 context.lineTo(100,100); // Draw edge context.stroke(); // Fill context.fill();Copy the code

Draw polygons

Taking the pentagon as an example,

var canvas = document.getElementById("square");
var context = canvas.getContext("2d"); // Draw a cabinet N deformation centered on 100,100 with radius 20. Each point is evenly distributed on the rounded corner. Start defining a sliver path context.moveto (100 + 20 * math.sin (0), 100-20 * math.cos (0)); Var delta = 2 * math.pi /5; var delta = 2 * math.pi /5; console.log(delta); Var Angle = 0;for(var i = 1; i < 5; I++){// Angle += delta; // Draw context.lineto (100 + 20* math.sin (Angle), 100-20 * math.cos (Angle)) by rotating the next vertex; } // Connect the last vertex to the starting point context.closepath (); // Start a new path from scratch context.stroke(); context.fill();Copy the code

Similarly, let’s draw a circle

var canvas = document.getElementById("square");
var context = canvas.getContext("2d"); // Draw a cabinet N deformation centered on 100,100 with radius 20. Each point is evenly distributed on the rounded corner. Start defining a sliver path context.moveto (100 + 20 * math.sin (0), 100-20 * math.cos (0)); Var delta = 2 * math.pi /500000; var delta = 2 * math.pi /500000; console.log(delta); Var Angle = 0;for(var i = 1; i < 500000; I++){// Angle += delta; // Draw context.lineto (100 + 20* math.sin (Angle), 100-20 * math.cos (Angle)) by rotating the next vertex; } // Connect the last vertex to the starting point context.closepath (); // Start a new path from scratch context.stroke(); context.fill();Copy the code

Nonzero winding principle

To test whether a point p inside the path, the use of zero around several principles, namely, an infinite extension from p along an arbitrary direction, or all the way to the ray path lie outside the area of a certain point, starting from 0 initialize a counter, now to enumerated through the ray path, when a path through the ray clockwise, counter plus 1, Counterclockwise minus 1. Finally, after enumerating all paths, if the timer is not 0, then P is considered to be in the path, and conversely, the counter is 0 and P is out of the path.

Js determines which is in the path and which is out of the path according to the non-zero winding principle for filling.

Graphic attributes

You can set the properties of graphics by setting fillStyle and other properties of the canvas context. For example, you can set the color, gradient, pattern and other styles when filling.

For canvas, the same context object will be returned every time it gets the context object, that is, the context object is singleton.

You can also use the save method to push the current state into the saved stack, and call the restore method to restore the state, i.e. the stack.

Canvas dimension coordinates

The default coordinate system of the canvas is the origin of the coordinates in the upper left corner (0,0), the value on the right side is large, and the value on the lower side is large. The coordinates are specified by floating point numbers, but they are not automatically converted to integers.

The canvas size cannot be changed arbitrarily, and any operation on any property will empty the entire canvas.

Coordinate transformation

The coordinates of each point are mapped to a CSS pixel, which is mapped to one or more device pixels. For a particular operation on the canvas, properties use the default coordinate system. The canvas and the current transformation matrix. The canvas also has the current transformation matrix, which is part of the state of the graph. The matrix defines the coordinate system for the current canvas. The canvas operation maps the point to the current coordinate system.

Coordinate transformation

When the c. ranslate(dx,dy) method is called, the following transformation is performed

Translate moves the coordinates up and down

x' = x + dy;
y' = y + dy;
Copy the code

Scale To scale, perform the following transformation

x' = sx * x;
y' = sy * y;
Copy the code

I rotate, and I do the following transformation

x' = x * cos(a) - y * sin(a);
y' = y * cos(a) - x * sin(a);
Copy the code

If you want to transform and then scale, you have to do the following transformation by mapping the existing frame to the points x prime and y prime in the frame and then converting to x prime and y prime.

x' ' = sx*x + dx;
y' ' = sy*y + dy;
Copy the code

If the transformation is reversed, perform the following transformation

x' ' = sx*(x + dx);
y' ' = sy*(y + dy);
Copy the code

This transformation is called an affine transformation, and it modifies the distance between points and the Angle between line segments. For parallel lines, affine transformations will also remain parallel. Affine transformations are described with six parameters as follows

x' = ax + cy + e;
y' = bx + dy + f;
Copy the code

Affine transformation is implemented by passing in parameters

For coordinate transformation, unless refresh, otherwise, has been drawn graph, will not disappear, all transformation, can not have been drawn graph change. Chestnut is as follows

var canvas = document.getElementById("square");
var context = canvas.getContext("2d"); BeginPath (); // Start a path context.beginPath(); // Start drawing subpath context.moveto (100,100); // Start drawing subpath context.moveto (100,100); // Continue drawing context.lineto (200,200); // Continue drawing context.lineto (200,200); // Draw edges context.stroke(); The context. Translate (200200); // Start a path context.beginPath(); // Start drawing subpath context.moveto (100,100); // Start drawing subpath context.moveto (100,100); // Continue drawing context.lineto (200,200); // Continue drawing context.lineto (200,200); // Draw edges context.stroke();Copy the code

A graph that has already been drawn does not change; the graph that has already been drawn changes

Koch snowflake

var canvas = document.getElementById("square");
var context = canvas.getContext("2d"); // Implement Koch snowflake through coordinate transformation // current state is pushedfunctionLeg (n) {// Save the state context.save(); / / the recursionif(n == 0){
        context.lineTo(50, 0);
    }else{// Define context.scale(1/2,1/2); Context. rotate(60 * (math.pi / 180)); leg(n - 1); context.rotate(-120 * (Math.PI / 180)); leg(n - 1); } // Coordinate restore transform context.restore(); // Restore the next coordinate to 0,0 context.translate(50, 0); } context.save(); context.moveTo(50, 50); // Draw the first leg(1); context.stroke();Copy the code

Draw filling curve

Draw some common graphics

var canvas = document.getElementById("square");
var context = canvas.getContext("2d"); // Tool function, Angle radiansfunction rads(x) {
    returnMath.PI * x / 180; } // Draw the garden context.beginPath(); The context. The arc (100100, 40, 0, rads (360).false);
context.stroke();
context.fill();
Copy the code

The same is true for plotting bezier curves.

Colors, transparency, gradients, patterns

To draw a gradient, use the createLinearGradient to get a context for the gradient, and process that context. The color is then set to the context of the gradient, the fillStyle property.

Line drawing

caps

For line segments, there are three capping methods, namely butt, square and round. After drawing the graph, the parameters are sharp, rounded and flat. LineCap properties

The text

Similar to CSS, baseline issues.

tailoring

The current path will also be clipped in, and everything outside the path will not be displayed.

shadow

Set the shadow property

The picture

The Canvas API supports bitmap images as well as canvas exports as images.

// Create an img elementlet img = document.createElement("img"); // Set the SRC attribute img.src = canvas.todataURL (); / / appended to the document behind the document. The body. The appendChild (img);Copy the code

synthetic

Some apis are not described

Pixel operations

Call getImageDate to return the ImageDate object. CreateImageDate () can be used to create a pixel container for dynamic blurring. It retrieves the pixel’s ImageDate object and then retrieves its Data property, which is an array. Is a dimensional array. Each of the four elements represents the red component, the green component, the blue component, and the transparency component. (Alpha component) its pigmentation is 0-1, that is, the array stored in the array element is the pigmentation value. Every four elements are iterated over. It then assigns 1/ n of its pigment value plus m/n of the previous color block to the new color block, as follows

// row is the number of rowsfor(var row = 0; row < height; Row++){// get the offset of the second element in each row, where width is the pigment block in the row. var i = row * width * 4; // Every 4 pigment values are processedfor(var col = 1; col < width; Col++, I + = 4) {/ / to red component processing data [I] = (data [I] + data [4] I - * m)/n. Data [I + 1] = (data[I + 1] + data[I + 1-4] * m)/n; Data [I + 2] = (data[I + 2] + data[I + 2-4] * m)/n; Data [I + 3] = (data[I + 3] + data[I + 3-4] * m)/n; }}Copy the code

And then copy the pigment block back. Each pixel takes up one byte, one four bytes.

Hit testing

The isPointInPath method is used to determine whether a point is in the current path. Match detection.

Hit detection can be interconverted with mouse events

But the coordinates need to be transformed.