Knowledge preparation-coordinate system
Before we really begin to summarize the transformations, we need to know about canvas's relevant coordinate system knowledge.
"Pixel coordinate system": in HTML, we set the canvas's properties: Width and height, which are in pixels, which describe the final rendering area of the canvas, which I call "pixel coordinates" (self-created, not very pertinent, laughed at), The coordinate system origin is in the upper-left corner of the canvas, and when the canvas is created, it will not change (of course, it will change when width and height are changed), the origin is always in the upper-left corner, and the number of pixels between x and Y is determined by width and height. To put it bluntly, this thing is like painting when the canvas, how much you give to how big.
Grid coordinate system: the coordinate system to use when drawing. All the units we draw with are not pixel coordinates, but the coordinate system called the grid. In order to draw graphs of various proportions within a finite canvas, we may want to make various transformations (translation, rotation, scaling) of this coordinate system. So the various transformations that are summarized later are for the grid coordinate system.
The relationship between the two coordinate systems is just like the display and the desktop, the display is equivalent to the pixel coordinate system, its points are fixed, what kind of what to create. Desktop is like a grid coordinate system, we can move, rotate the desktop, modify the desktop resolution to see more content.
In canvas, by default, grid coordinates correspond to pixel coordinates of one by one, and the origin is in the upper-left corner, which corresponds to 1 pixel units per grid unit. The position of all objects in the canvas is relative to the origin of the grid coordinates. As shown in the following figure, by default, the blue squares are positioned at the left X units and the top Y units (coordinates (x, y)).
Knowledge Preparation-Status hold
before you formally introduce a transformation, you need to understand the two methods necessary to draw complex graphics, which are widely used in deformation.
Save Status: Context.save ()
Recovery state: Context.restore ()
The Save and restore methods are used to save and restore the canvas state without parameters. The state of the canvas is a snapshot of all styles and variants applied to the current screen. The
Canvas state is saved as a heap (stack), and each time the Save method is called, the current state is pushed into the heap and saved. This state includes:
The current applied variants (i.e., move, rotate, and scale);
All styles: Strokestyle,fillstyle, Globalalpha, LineWidth, LineCap, LineJoin, Miterlimit, Shadowoffsetx,shadowoffsety, Shadowblur, Shadowcolor, globalcompositeoperation value;
· The current crop path (clipping path).
You can call any number of Save methods to put the canvas state into the stack. Each time the restore method is called, the Last Saved state pops out of the heap and all settings are restored.
The following example is an easy way to explain how save and restore are used:
function Draw () { var ctx = document.getElementById (' Lesson01 '). 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}
As you can see in the example above, it would be cumbersome to manually modify the values of each style each time, especially when the values of the styles are very large and error-prone. It is very convenient to use Save/restore at this time.
Transform
As you learn about graphics, there are several transformations: moving, rotating, and zooming. In order to clarify the effect of the transformation, we must understand that the goal of the transformation is which. As I said above, these transformations are for the grid coordinate system. Let's look at these transformations separately.
Pan Transform: 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 left and right offset,Y is the upper and lower offset.
It is a good habit to save the state before making a transformation. In most cases, calling therestore method is much simpler than manually recovering the original state. Especially in the loop, pay more attention to save and restore the state of canvas.
Rotation transformation: Rotates the grid coordinate system clockwise along its origin to the specified angle.
Context.rotate (angle)
This method accepts only one parameter: the angle of rotation Canvas.
Zoom Transform: The coordinate units of the grid coordinate system are scaled down or zoomed in at the specified scale.
Context.scale (x, y)
Scale method accepts two parameters. x,y are scaling factors for both the horizontal and vertical axes, both of which must be positive. The value is smaller than 1.0, which is larger than
because the pixel size is constant, so the actual effect of this transformation is the same size of the canvas, can draw more or less things.
Transformation example is as follows:
Function Draw () {
var ctx = document.getElementById (' Lesson01 '). GetContext (' 2d ');
ctx.linewidth = 1.5;
Ctx.fillrect (0,0,300,300);
Ctx.translate (150,150);
Ctx.rotate (MATH.PI/4);
Ctx.scale (0.5,0.5);
Ctx.clearrect ( -40,-40, 80,80);
}
Transformation matrices: All transformations can be expressed in matrices.
You can set the transformation matrix directly in the following two ways:
Context.transform (M11, M12, M21, M22, DX, dy)
Context.settransform (M11, M12, M21, M22, DX, dy)
The first method directly adds the current transformation matrix to the following matrix (note the order of the permutations ):
M11 M21 DX
M12 M22 Dy
0 0 1
The second method resets the current transformation matrix to the unit matrix, and then calls the transform method with the same parameters .
HTML5 Canvas FillRect coordinate and size problem solving methods
The width and height of the canvas must be inline in the canvas label
<!doctype html>
<meta charset= "UTF-8" >
<title>Document</title>
<body>
<canvas id= ' MyCanvas ' width= ' 200px ' height= ' 200px ' style= ' Background:yellow ' ></canvas>
<script>
var c = document.getElementById (' MyCanvas ');
var ctx = C.getcontext ("2d");
ctx.fillstyle= ' #f36 ';
Ctx.fillrect (100, 100, 100, 100);
</script>
</body>
All the transformations start from the transformation matrix, so the translation, rotation, scaling can be replaced by the corresponding matrix,
Pan: Context.translate (dx,dy) can be replaced with context.transform (1,0,0,1,dx,dy) or Context.transform (0,1,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/ , Math.Cos (θ*math.pi/180), 0,0)
or Context.transform (-math.sin (θ*math.pi/180), Math.Cos (θ*math.pi/180), Math.Cos (θ*math.pi/180), Math.sin (θ* math.pi/180), 0,0) instead.
Scaling: Context.scale (SX, SY) can be replaced with context.transform (sx,0,0,sy,0,0) or Context.transform (0,sy,sx,0,0,0).
By default, we always draw one graphic on top of another, which means that the result of the drawing is subject to the order in which the drawing is drawn. In most cases, this is not enough, and setting a composite property is the problem of what happens when the graphics overlap. We use the Globalcompositeoperation property to change the default practice.
Globalcompositeoperation = Type
Type is one of the following 12 string values:
Source-over: This is the default setting and the new graphic will be overwritten with the original content.
source-in: The new graphic will only appear in the part that overlaps with the original content. All other areas become transparent.
Ource-out: The result is that only the parts of the new drawing that do not overlap the original content are drawn.
Source-atop: The part of the new drawing that overlaps with the original content is drawn and overlaid on the original content.
Lighter: Two The overlapping parts of the drawing are added to the color processing.
XOR: The overlapping parts become transparent.
Destination-over: New graphics will be drawn under the original content.
destination-in: The portion of the original content that overlaps with the new shape is retained and the other areas become transparent.
Destination-out: Portions of the original content that do not overlap the new shapes are retained.
destination-atop: The portion of the original content that overlaps with the new content is retained and a new graphic is drawn under the original content.
Darker: Two The overlapping portions of the graph are treated as subtractive.
copy: Only new graphics are preserved and others are erased.
Suppose we first draw a blue rectangle and then draw a red circle, the result of applying these 12 combination settings is as follows:
Cutting
One of the problems associated with composition is cropping. In fact, when drawing the path, the last step is to draw the graph to the canvas function in addition to the stroke and fill, there is clip; When you end a path with a clip, the currently drawn shape is treated as a clipping path, and only the shapes within the clipping path are displayed. The crop path is part of the canvas state and can be saved. If we want to preserve the original crop path when we create a new crop path, all we need to do is to save the state of the canvas.
For example, the following example is to draw the mask layer background and clipping path, and then the drawing is only visible within the clipping path:
functionDraw () {varCTX = document.getElementById (' Lesson01 '). GetContext (' 2d ')); //Draw Mask BackgroundCtx.fillrect (0,0,150,150); Ctx.translate (75,75); //Create a circular clipping pathCtx.beginpath (); Ctx.arc (0,0,60,0,math.pi*2,true); Ctx.clip (); //Draw Background varLingrad = 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(varj=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 ()) +2); Ctx.restore (); } } functionDrawstar (ctx,r) {ctx.save (); Ctx.beginpath () Ctx.moveto (R,0); for(vari=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
Since we are using scripts to manipulate canvas objects, it is fairly easy to implement some interactive animations. However, canvas is not designed specifically for animations (unlike Flash), so there are some restrictions on how to operate.
The biggest limitation is that once the image is drawn, it stays that way. If we need to move it, we have to redraw everything. Repainting is quite time consuming, and performance depends on the speed of the computer.
Steps for basic animations:
1. To draw a frame, you need some of the following steps:
(1) Clear canvas
Unless the next draw will be completely filled with canvas (such as a background map), you will need to clear all. The simplest approach is to use the Clearrect method.
(2) Save Canvas State
If you want to change some of the settings that will change the canvas state (style, warp, etc.) and the original state when you draw each frame, you need to save it first.
(3) Drawing animated graphics (animated shapes)
This step is to redraw the animation frame.
(4) Restore the canvas state
If you have saved the state of the canvas, you can restore it first, and then redraw the next frame.
2. According to certain settings to calculate the transformation of the graph, redraw the new frame, the process of drawing each frame is the same.
There are usually two ways to set the frequency of repainting:
(1) Timed redraw
The first approach is to control the redraw at a set point in time by using the SetInterval and SetTimeout methods.
SetInterval (animateshape,500);
SetTimeout (animateshape,500);
SetTimeout and setinterval have the same syntax. They all have two parameters, one is the code string to execute, and one is the time interval in milliseconds, and the code executes after that time period.
However, the two functions are still different, setinterval after the execution of the code, after the fixed time interval, it will also automatically repeat the code, and settimeout only one time to execute the code.
If you don't need any interaction, it's best to use the SetInterval method to perform a redraw at timed intervals.
(2) Redraw specific events
The second way, we can use the user input to achieve the manipulation. If a game needs to be done, we can control the animation by listening to events triggered during user interaction, such as various keyboard,mouse events of document.
The following example draws a clock in the first way:
functioninit () {clock (); SetInterval (Clock,1000); } functionclock () {varnow =NewDate (); varCTX = document.getElementById (' Lesson01 '). 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 MarksCtx.save (); for(vari=0;i<12;i++) {Ctx.beginpath (); Ctx.rotate (Math.PI/6); Ctx.moveto (100,0); Ctx.lineto (120,0); Ctx.stroke (); } ctx.restore (); //Minute MarksCtx.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 (); varSEC =now.getseconds (); varMin =now.getminutes (); varhr =now.gethours (); HR= hr>=12? Hr-12: HR; Ctx.fillstyle= "BLACK"; //Write HoursCtx.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 MinutesCtx.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 secondsCtx.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 (95,0,10,0,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 (); }
TML5 's Canvas