Knowledge preparation-Coordinate System
Before we start the summary transformation, we need to first learn about the coordinate system of canvas.
"Pixel coordinate system": in HTML, we will set the attributes of the canvas: width and height. They are in pixels and describe the final rendering area of the canvas, my image is called "pixel coordinates" (self-created, not very relevant, experts don't laugh). This Coordinate System origin is in the upper left corner of the canvas. After the canvas is created, it will not change (of course, it will change when the width and height are modified), the origin is always in the upper left corner; the number of pixels of x and y is determined by the width and height. To put it bluntly, this is like a canvas when you draw a picture. It's as big as you give it.
Grid coordinate system: the coordinate system used for drawing. When we plot, all units use not the pixel coordinates, but the coordinate system called the grid. To draw a chart of various proportions within a limited canvas, we may need to perform various transformations (translation, rotation, and scaling) on the coordinate system ). Therefore, all the transformations summarized later are for the grid coordinate system.
The relationship between the two coordinate systems is like the relationship between the display and the desktop. The display is equivalent to the pixel coordinate system, and its points are fixed. The desktop is like a grid coordinate system. We can move the desktop at any time, rotate the desktop, and modify the desktop resolution to view more content.
In canvas, by default, the grid coordinates correspond to the pixel coordinates one by one, and the origin is in the upper left corner. Each grid unit corresponds to one pixel unit. The positions of all objects in the canvas are relative to the origin of the grid coordinates. As shown in the following figure, by default, the position of the blue square is the unit x on the left and the unit y on the top (coordinates (x, y )).
Knowledge preparation-status maintenance
Before formally introducing deformation, you also need to understand two methods that are essential for drawing Complex Images. These two methods are widely used in deformation.
Save status: context. save ()
Recovery status: context. restore ()
The save and restore methods are used to save and restore the canvas state without parameters. The canvas status is a snapshot of all styles and variants applied to the current screen.
The canvas status is saved as a stack. Each time the save method is called, the current status is pushed to the stack for saving. This status includes:
• Deformation of the current application (I .e. moving, rotating, and scaling );
• All styles: Values of strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, and globalCompositeOperation;
• The current cropping path (clipping path ).
You can call the save method multiple times to import the canvas status to the stack. Each time the restore method is called, the last saved state pops up from the heap and all settings are restored.
The following example shows how to use save and restore:
Function draw (){
Var ctx = document. getElementById ('leson01'). getContext ('2d ');
Ctx. fillRect (0, 0, 150,150); // Draw a rectangle with default settings
Ctx. save (); // Save the default state
Ctx. fillStyle = '# 09f' // Make changes to the settings
Ctx. fillRect (15, 15, 120,120); // Draw a rectangle with new settings
Ctx. save (); // Save the current state
Ctx. fillStyle = '# fff' // Make changes to the settings
Ctx. globalAlpha = 0.5;
Ctx. fillRect (30, 30, 90, 90); // Draw a rectangle with new settings
Ctx. restore (); // Restore previous state
Ctx. fillRect (45, 45, 60, 60); // Draw a rectangle with restored settings
Ctx. restore (); // Restore original state
Ctx. fillRect (60, 60, 30, 30); // Draw a rectangle with restored settings
}
In the above example, it can be seen that if you manually modify the values of each style each time, it will be very troublesome, especially when there are many style values, it is more prone to errors. At this time, it is very convenient to use save/restore.
Transform
All those who have learned graphics know that there are several types of transformations: movement, rotation, and scaling. To find out the effect of the transformation, we must understand the target of the transformation. As I mentioned above, these transformations are for the grid coordinate system. Let's take a look at these transformations.
Translation Transformation: moves the origin of the grid coordinate system to the specified offset.
Context. translate (x, y)
The translate method accepts two parameters. X is the offset between the left and right sides, and y is the upper and lower offset.
It is a good habit to save the status before deformation. In most cases, calling the restore method is much easier than manually restoring the original state. Especially in the loop, you must pay attention to saving and restoring the canvas status.
Rotation and Transformation: rotate the grid coordinate system clockwise along the origin of the specified angle.
Context. rotate (angle)
This method only accepts one parameter: angle, which is clockwise and measured in radians. The center of the rotation is always the origin of the canvas.
Scaling: scale down or zoom in the coordinate units of the grid coordinate system according to the specified proportion.
Context. scale (x, y)
The scale method accepts two parameters. X and y are the zooming factors of the horizontal and vertical axes respectively. They must both be positive values. If the value is smaller than 1.0, it means to zoom in. If the value is greater than 1.0, it means to zoom in. If the value is 1.0, there is no effect.
Because the pixel size remains unchanged, the actual effect of this change is that there are more or less items to be painted in the canvas of the same size.
The conversion example is as follows:
Function draw (){
Var ctx = document. getElementById ('leson01'). getContext ('2d ');
Ctx. lineWidth = 1.5;
Ctx. fillRect (300,300 );
Ctx. translate (150,150 );
Ctx. rotate (Math. PI/4 );
Ctx. scale (0.5, 0.5 );
Ctx. clearRect (-40,-40, 80, 80 );
}
Transformation Matrix: all transformations can be expressed in a matrix.
You can use the following two methods to directly set the transformation matrix:
Context. transform (m11, m12, m21, m22, dx, dy)
Context. setTransform (m11, m12, m21, m22, dx, dy)
The first method is to multiply the current deformation matrix by the upper and lower matrices (pay attention to the order of arrangement ):
M11 m21 dx
M12 m22 dy
0 0 1
The second method resets the current deformation matrix as the matrix, and then calls the transform method with the same parameters.
Function draw (){
Var canvas = document. getElementById ("lesson01 ");
Var ctx = canvas. getContext ("2d ");
Var sin = Math. sin (Math. PI/6 );
Var cos = Math. cos (Math. PI/6 );
Ctx. translate (200,200 );
Var c = 0;
For (var I = 0; I <= 12; I ++ ){
C = Math. floor (255/12 * I );
Ctx. fillStyle = "rgb (" + c + "," + c + "," + c + ")";
Ctx. fillRect (0, 0,100, 10 );
Ctx. transform (cos, sin,-sin, cos, 0, 0 );
}
Ctx. setTransform (-1, 0, 0, 1,200,200 );
Ctx. fillStyle = "rgba (255,128,255, 0.5 )";
Ctx. fillRect (0, 50,100,100 );
}
All transformations start with transformation matrices. Therefore, the translation, rotation, and scaling mentioned above can be replaced by the corresponding matrices. Students who are proficient in mathematics can deduce them by themselves:
Translation: context. translate (dx, dy) can be replaced by context. transform (, dx, dy) or context. transform (, 1, 0.dx, dy.
Rotation: context. rotate (θ) can use context. transform (Math. cos (θ * Math. PI/180), Math. sin (θ * Math. PI/180),-Math. sin (θ * Math. PI/180), Math. cos (θ * Math. PI/180),) or
Context. transform (-Math. sin (θ * Math. PI/180), Math. cos (θ * Math. PI/180), Math. cos (θ * Math. PI/180), Math. sin (θ * Math. PI/180),) instead.
Zoom: context. scale (sx, sy) can use context. transform (sx, 0, 0, sy, 0, 0) or context. transform (0, sy, sx, 0, 0, 0) instead.
Combination
By default, we always draw one image on the other, that is, the drawing result is subject to the order of the drawing. In most cases, this is not enough. Setting the composite attribute is to solve the effect of overlapping images. We use the globalCompositeOperation attribute to change the default practice.
GlobalCompositeOperation = type
Type is one of the following 12 string values:
• Source-over (default): This is the default setting. The new image will overwrite the original content.
• Source-in: new images only overlap with original content. Other regions are transparent.
• Ource-out: only the parts in the new image that do not overlap with the original content will be drawn.
• Source-atop: the overlapping parts of the new image and the original content will be drawn and overwrite the original content.
• Lighter: the overlapping parts of the two images are colored.
• Xor: overlapping parts become transparent.
• Destination-over: Creates a new image under the original content.
• Destination-in: the overlapping parts of the original content and the new image will be retained, and other areas will become transparent.
• Destination-out: the original content that does not overlap with the new image will be retained.
• Destination-atop: the overlapping parts of the original content will be retained and new images will be drawn under the original content.
• Darker: the overlapping parts of the two images are used for color reduction.
• Copy: only new images are retained, and others are cleared.
Suppose we first draw a blue rectangle and then draw a red circle, then apply the 12 combination settings as follows:
Note: If the set attribute value does not work, the current browser does not support this combination attribute value.
Crop
A problem related to the combination is cropping. In fact, when drawing the path, the last step is to draw the graph to the canvas function in addition to stroke and fill, there is also clip; when the path ends with clip, the currently drawn image is used as the cropping path. Only the image in the cropping path is displayed. The cropping path is part of the canvas status and can be saved. If you want to retain the original cropping path when creating a new cropping path, you need to save the canvas status.
For example, the following example is to first draw the background and crop path of the Mask layer, and then the drawn image is visible only in the crop path:
Function draw (){
Var ctx = document. getElementById ('leson01'). getContext ('2d ');
// Draw mask background
Ctx. fillRect (150,150 );
Ctx. translate (75, 75 );
// Create a circular clipping path
Ctx. beginPath ();
Ctx. arc (0, 0, 60, 0, Math. PI * 2, true );
Ctx. clip ();
// Draw background
Var lingrad = ctx. createLinearGradient (0,-75, 0, 75 );
Lingrad. addColorStop (0, '#232256 ');
Lingrad. addColorStop (1, '#143778 ');
Ctx. fillStyle = lingrad;
Ctx. fillRect (-75,-75,150,150 );
// Draw stars
For (var j = 1; j <50; j ++ ){
Ctx. save ();
Ctx. fillStyle = '# fff ';
Ctx. translate (75-Math.floor (Math. random () * 150 ),
75-Math.floor (Math. random () * 150 ));
DrawStar (ctx, Math. floor (Math. random () * 4) + 2 );
Ctx. restore ();
}
}
Function drawStar (ctx, r ){
Ctx. save ();
Ctx. beginPath ()
Ctx. moveTo (r, 0 );
For (var I = 0; I <9; I ++ ){
Ctx. rotate (Math. PI/5 );
If (I % 2 = 0 ){
Ctx. lineTo (r/0.525731) * 0.200811, 0 );
} Else {
Ctx. lineTo (r, 0 );
}
}
Ctx. closePath ();
Ctx. fill ();
Ctx. restore ();
}
Animation
Because we use scripts to manipulate canvas objects, it is quite easy to implement interactive animations. However, canvas is not designed specifically for animation (unlike Flash), so operations may be limited.
The biggest limitation is that once an image is drawn, it will always be like that. If you need to move it, we have to re-paint everything. Re-painting is quite time-consuming, and the performance depends on the speed of the computer.
Basic animation steps:
1. To draw a frame, perform the following steps:
(1) Clear the canvas
Unless the content to be drawn is fully filled with a canvas (for example, a background image), you need to clear all the items. The simplest way is to use the clearRect method.
(2) Save the canvas status
If you want to change the settings that will change the canvas state (style, deformation, and so on) and the canvas state is original when every frame is drawn, you need to save it first.
(3) drawing animated images (animated shapes)
This step re-draws the animation frame.
(4) restore the canvas status
If you have saved the canvas status, you can restore it and redraw the next frame.
2. Calculate the graph transformation according to certain settings, and redraw new frames. The process of drawing each frame is the same.
There are usually two ways to set the repainting frequency:
(1) timed re-painting
The first method is to use the setInterval and setTimeout methods to control the re-painting at the specified time point.
SetInterval (animateShape, 500 );
SetTimeout (animateShape, 500 );
The setTimeout and setInterval syntaxes are the same. They all have two parameters: one is the code string to be executed, and the other is the interval in milliseconds. after that period, the code will be executed.
However, there are differences between the two functions. After the setInterval code is executed, it automatically repeats the code after the fixed interval, setTimeout only executes the code once.
If you do not need any interactive operations, it is best to use the setInterval method to perform regular re-painting.
(2) redraw a specific event
Second, we can use user input for control. If you want to make a game, you can control the animation effect by monitoring events triggered during user interaction (such as various keyboard and mouse events of the document.
The following example uses the first method to draw a clock:
Function init (){
Clock ();
SetInterval (clock, 1000 );
}
Function clock (){
Var now = new Date ();
Var ctx = document. getElementById ('leson01'). getContext ('2d ');
Ctx. save ();
Ctx. clearRect (0, 0, 150,150 );
Ctx. translate (75, 75 );
Ctx. scale (0.4, 0.4 );
Ctx. rotate (-Math. PI/2 );
Ctx. strokeStyle = "black ";
Ctx. fillStyle = "white ";
Ctx. lineWidth = 8;
Ctx. lineCap = "round ";
// Hour marks
Ctx. save ();
For (var I = 0; I <12; I ++ ){
Ctx. beginPath ();
Ctx. rotate (Math. PI/6 );
Ctx. moveTo (100,0 );
Ctx. lineTo (120,0 );
Ctx. stroke ();
}
Ctx. restore ();
// Minute marks
Ctx. save ();
Ctx. lineWidth = 5;
For (I = 0; I <60; I ++ ){
If (I % 5! = 0 ){
Ctx. beginPath ();
Ctx. moveTo (117,0 );
Ctx. lineTo (120,0 );
Ctx. stroke ();
}
Ctx. rotate (Math. PI/30 );
}
Ctx. restore ();
Var sec = now. getSeconds ();
Var min = now. getMinutes ();
Var hr = now. getHours ();
Hr = hr> = 12? Hr-12: hr;
Ctx. fillStyle = "black ";
// Write Hours
Ctx. save ();
Ctx. rotate (hr * (Math. PI/6) + (Math. PI/360) * min + (Math. PI/21600) * sec)
Ctx. lineWidth = 14;
Ctx. beginPath ();
Ctx. moveTo (-20, 0 );
Ctx. lineTo (80, 0 );
Ctx. stroke ();
Ctx. restore ();
// Write Minutes
Ctx. save ();
Ctx. rotate (Math. PI/30) * min + (Math. PI/1800) * sec)
Ctx. lineWidth = 10;
Ctx. beginPath ();
Ctx. moveTo (-28, 0 );
Ctx. lineTo (112,0 );
Ctx. stroke ();
Ctx. restore ();
// Write seconds
Ctx. save ();
Ctx. rotate (sec * Math. PI/30 );
Ctx. strokeStyle = "# D40000 ";
Ctx. fillStyle = "# D40000 ";
Ctx. lineWidth = 6;
Ctx. beginPath ();
Ctx. moveTo (-30, 0 );
Ctx. lineTo (83,0 );
Ctx. stroke ();
Ctx. beginPath ();
Ctx. arc (0, 0, 10, 0, Math. PI * 2, true );
Ctx. fill ();
Ctx. beginPath ();
Ctx. arc (, Math. PI * 2, true );
Ctx. stroke ();
Ctx. fillStyle = "#555 ";
Ctx. arc (0, 0, 3, 0, Math. PI * 2, true );
Ctx. fill ();
Ctx. restore ();
Ctx. beginPath ();
Ctx. lineWidth = 14;
Ctx. strokeStyle = '#325FA2 ';
Ctx. arc (0, 0, 142,0, Math. PI * 2, true );
Ctx. stroke ();
Ctx. restore ();
}
Practical reference:
Official reference documentation and API details: http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html
Authoritative development entry: https://developer.mozilla.org/cn/Canvas_tutorial
From the autumn army