来源:未知 时间:2014-11-07 14:49 作者:xxadmin 阅读:次
[导读] 第1页绘制椭圆 把现实世界当中的物体模拟到计算机当中,一些简单的物理实验、碰撞旋转等等难度还是不算很大,难度较大的应当算流体模拟。 本文将在Canvas当中模拟出一个2D平面内...
第1页绘制椭圆 把现实世界当中的物体模拟到计算机当中,一些简单的物理实验、碰撞旋转等等难度还是不算很大,难度较大的应当算流体模拟。 本文将在Canvas当中模拟出一个2D平面内的水珠,涉及的知识点和技巧包括:Jscex基础知识,贝塞尔曲线的绘制,合理利用CanvasRenderingContext2D的translate和rotate等API。 绘制椭圆 在模拟水滴之前,我们先思考一下怎么在canvas当中绘制一个椭圆。 大家可以很容易想到 下面几种方案: 1.根据椭圆笛卡尔坐标系方程绘制 2.根据椭圆极坐标方程绘制 3.根据椭圆曲率变化绘制 4.利用四条贝塞尔曲线绘制 第四种,也是性能最好的一种,这样可以避免复杂的计算,充分利用CanvasRenderingContext2D的API(API的性能是通过严格测试,一般情况下比较靠谱). 所以我们采用第四种方式来绘制椭圆。 var canvas; var ctx; 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.border=”1″ Height); drawEllipse(10, 10, 40, 82); (改变drawEllipse的四个参数试试) 旋转椭圆 这里的旋转不是绕上面的drawEllipse的前两个参数x,y旋转,二是绕椭圆的中心旋转。所以仅仅 CanvasRenderingContext2D.rotate是不够的,因为CanvasRenderingContext2D.rotate是绕画 布的左上角(0,0)旋转。所以我们先要把(0,0)通过CanvasRenderingContext2D.translate到椭圆的中心,然后再 drawEllipse(-a/2, –b/2, a, b). 上面这句话,就是绕中心旋转的核心。这里还可以推广到任意图形或者图片(假设有约定的中心)。如图: 第2页旋转椭圆 然后我们就可以先绘制一个鸟巢出来: html> head> script src=”http://files.cnblogs.com/iamzhanglei/jscex.jscexRequire.min.js” type=”text/javascript”>script> head> body> style type=”text/css”> input.css3btn 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 #38538c; 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.css3btn:hover box-shadow: inset 0 0px 20px 1px #87adff, 0px 1px 0 #1d2c4d, 0 3px 0px #1f3053, 0 4px 4px 1px #111111; cursor: pointer; input.css3btn:active box-shadow: inset 0 1px 10px 1px #5c8bee, 0 1px 0 #1d2c4d, 0 2px 0 #1f3053, 0 4px 3px 0 #111111; style> canvas width=”350″ border=”1″ 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() { 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 type=”button” value=”run” onclick=”return Button2_onclick()” /> input type=”button” value=”stop” onclick=”return Button1_onclick()” /> body> html> 第3页绘制水滴
绘制水滴 旋转的椭圆和鸟巢神马的和水滴有什么关系呢? 我们通过改变椭圆的长轴和短轴,令其非常接近圆形(只能接近,不能等于圆形),然后每次旋转擦除画布,就可以达你预想不到的效果! 这里需要注意的是,擦除画布不再是一句 CanvasRenderingContext2D.clearRect(0,0,canvas.width,canvas.border=”1″ Height)就可以,因为画布已经旋转和画布原点已经translate,所以我们使用 ctx.clearRect(-canvas.width, -canvas.border=”1″ Height, 2 * canvas.width, 2 * canvas.border=”1″ Height)来擦除画布。 我们画一个长轴42,短轴40的椭圆,旋转并擦除画布: function drawEllipse(x, y, w, h) { ctx.clearRect(-canvas.width, -canvas.border=”1″ Height, 2 * canvas.width, 2 * canvas.border=”1″ 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)); })) 会是什么效果呢? 在线演示效果查看 http://www.cnblogs.com/iamzhanglei/archive/2011/12/12/2284188.html 现在大家可以看到一个晃动的水珠了 |
自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习
京ICP备14009008号-1@版权所有www.zixuephp.com
网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com