It is difficult to simulate objects in the real world into a computer. Some simple physical experiments, collision and rotation, and so on should be considered fluid simulation.
In this article, we will simulate a 2D plane of water beads in Canvas. The knowledge points and skills involved include: Basic knowledge of Jscex, the drawing of the besell curve, and the rational use of CanvasRenderingContext2D's translate and rotate APIs.
Draw an ellipse
Before simulating water drops, let's first think about how to draw an ellipse in the canvas.
You can easily think of the following solutions:
1. Draw Based on Cartesian coordinate system equations
2. Draw Based on the elliptic polar coordinate equation
3. Draw Based on Elliptical curvature changes
4. Draw with four besell Curves
Fourth, it is also the best performance, which can avoid complicated computing and make full use of the CanvasRenderingContext2D API (the API performance is strictly tested and generally reliable ).
So we use the fourth method to draw an ellipse.
Var canvas;
Var ctx;
Canvas = document. getElementById ("myCanvas1 ");
Ctx = canvas. getContext ("2d ");
Ctx. strokeStyle = "# fff ";
Function drawEllipse (x, y, w, h ){
Var k = 0.5522848;
Var ox = (w/2) * k;
Var oy = (h/2) * k;
Var xe = x + w;
Var ye = y + h;
Var xm = x + w/2;
Var ym = y + h/2;
Ctx. beginPath ();
Ctx. moveTo (x, ym );
Ctx. bezierCurveTo (x, ym-oy, xm-ox, y, xm, y );
Ctx. bezierCurveTo (xm + ox, y, xe, ym-oy, xe, ym );
Ctx. bezierCurveTo (xe, ym + oy, xm + ox, ye, xm, ye );
Ctx. bezierCurveTo (xm-ox, ye, x, ym + oy, x, ym );
Ctx. stroke ();
}
Ctx. clearRect (0, 0, canvas. width, canvas. height );
DrawEllipse (10, 10, 40, 82 );
(Try changing the four parameters of drawEllipse)
Rotate an ellipse
The rotation here is not to rotate around the first two parameters x and y of drawEllipse above, and the second is to rotate around the center of the elliptic. Therefore, CanvasRenderingContext2D. rotate is not enough because CanvasRenderingContext2D. rotate rotates around the upper left corner of the canvas. Therefore, we need to first (0, 0) to the center of the elliptic through CanvasRenderingContext2D. translate, and then drawEllipse (-a/2,-B/2, a, B ).
The above sentence is the core of the circle center. It can also be promoted to any image or image (assuming there is an agreed center ).
Then we can draw a nest first:
<Html>
<Head>
<Script src = "http://files.cnblogs.com/iamzhanglei/jscex.jscexRequire.min.js" type = "text/javascript"> </script>
</Head>
<Body>
<Style type = "text/css">
Input.css 3btn
{
Background:-moz-linear-gradient (270deg, # d2ebf8, #0c8ab5 );
Background:-webkit-linear-gradient (top, # d2ebf8, #0c8ab5 );
Background:-o-linear-gradient (top, # d2ebf8, #0c8ab5 );
Filter: progid: DXImageTransform. Microsoft. Gradient (GradientType = 0, StartColorStr = '# 000099CC', EndColorStr = '# FF0087B4 ');
Border-top: 1px solid # limit 38C;
Border-right: 1px solid # 1f2d4d;
Border-bottom: 1px solid #151e33;
Border-left: 1px solid # 1f2d4d;
Border-radius: 4px;
Box-shadow: inset 0 1px 10px 1px # 5c8bee, 0px 1px 0 # 1d2c4d, 0 2px 0px #1f3053, 0 4px 4px 1px #111111;
Color: # f0f0f0;
Font: bold 20px "helvetica neue", helvetica, arial, sans-serif;
Padding: 10px 0 10px 0;
Text-align: center;
Text-shadow: 0px-1px 1px # 1e2d4d;
Width: 150px;
Background-clip: padding-box;
}
Input.css 3btn: hover
{
Box-shadow: inset 0 0px 20px 1px #87 adff, 0px 1px 0 # 1d2c4d, 0 3px 0px #1f3053, 0 4px 4px 1px #111111;
Cursor: pointer;
}
Input.css 3btn: active
{
Box-shadow: inset 0 1px 10px 1px # 5c8bee, 0 1px 0 # 1d2c4d, 0 2px 0 #1f3053, 0 4px 3px 0 #111111;
Margin-top: 1px;
}
</Style>
<Canvas id = "myCanvas2" width = "350" height = "350" style = "border: solid 15px #222; background-color: #111;
Color: # CCC; ">
Your browser does not support the canvas element.
</Canvas>
<Script>
Var canvas;
Var ctx;
Var px = 0;
Var py = 0;
Function init (){
Canvas = document. getElementById ("myCanvas2 ");
Ctx = canvas. getContext ("2d ");
Ctx. strokeStyle = "# fff ";
Ctx. translate (70, 70 );
}
Init ();
Var I = 0;
Function drawEllipse (x, y, w, h ){
Var k = 0.5522848;
Var ox = (w/2) * k;
Var oy = (h/2) * k;
Var xe = x + w;
Var ye = y + h;
Var xm = x + w/2;
Var ym = y + h/2;
Ctx. beginPath ();
Ctx. moveTo (x, ym );
Ctx. bezierCurveTo (x, ym-oy, xm-ox, y, xm, y );
Ctx. bezierCurveTo (xm + ox, y, xe, ym-oy, xe, ym );
Ctx. bezierCurveTo (xe, ym + oy, xm + ox, ye, xm, ye );
Ctx. bezierCurveTo (xm-ox, ye, x, ym + oy, x, ym );
Ctx. stroke ();
Ctx. translate (x + 70, y + 100 );
Px =-70;
Py =-100;
Ctx. rotate (10 * Math. PI * 2/360 );
}
Var ct;
Var drawAsync = eval (Jscex. compile ("async", function (ct ){
While (true ){
DrawEllipse (px, py, 140,200)
$ Await (Jscex. Async. sleep (200, ct ));
}
}))
Function Button1_onclick (){
Ct. cancel ();
}
Function Button2_onclick (){
Ct = new Jscex. Async. CancellationToken ();
DrawAsync (ct). start ();
}
</Script>
<Br/>
<Input id = "Button2" class = "css3btn" type = "button" value = "run" onclick = "return Button2_onclick ()"/>
<Input id = "Button1" class = "css3btn" type = "button" value = "stop" onclick = "return button#onclick ()"/>
</Body>
</Html>
Draw Water Drops
What is the relationship between the rotating oval and the bird's nest and the water drops?
By changing the long and short axes of an ellipse, we can make it very close to the Circle (only close, not equal to the circle), and then erase the canvas every time you rotate it to achieve the effect you don't think!
It should be noted that the erased canvas is no longer a CanvasRenderingContext2D sentence. clearRect (0, 0, canvas. width, canvas. height), because the canvas has been rotated and the canvas origin has been translated, we use ctx. clearRect (-canvas. width,-canvas. height, 2 * canvas. width, 2 * canvas. height) to erase the canvas.
Let's draw an ellipse with a long axis 42 and a short axis 40, rotate and erase the canvas:
Function drawEllipse (x, y, w, h ){
Ctx. clearRect (-canvas. width,-canvas. height, 2 * canvas. width, 2 * canvas. height );
Var k = 0.5522848;
Var ox = (w/2) * k;
Var oy = (h/2) * k;
Var xe = x + w;
Var ye = y + h;
Var xm = x + w/2;
Var ym = y + h/2;
Ctx. beginPath ();
Ctx. moveTo (x, ym );
Ctx. bezierCurveTo (x, ym-oy, xm-ox, y, xm, y );
Ctx. bezierCurveTo (xm + ox, y, xe, ym-oy, xe, ym );
Ctx. bezierCurveTo (xe, ym + oy, xm + ox, ye, xm, ye );
Ctx. bezierCurveTo (xm-ox, ye, x, ym + oy, x, ym );
Ctx. stroke ();
Ctx. translate (x + 20, y + 21 );
Px =-20;
Py =-21;
Ctx. rotate (10 * Math. PI * 2/360 );
}
Var ct;
Var drawAsync = eval (Jscex. compile ("async", function (ct ){
While (true ){
DrawEllipse (px, py, 40, 42)
$ Await (Jscex. Async. sleep (10, ct ));
}
}))