日期:2014-05-17  浏览次数:20630 次

HTML5实验:JavaScript模拟流体效果(转)

?

?把现实世界当中的物体模拟到计算机当中,一些简单的物理实验、碰撞旋转等等难度还是不算很大,难度较大的应当算流体模拟。

  本文将在Canvas当中模拟出一个2D平面内的水珠,涉及的知识点和技巧包括:Jscex基础知识,贝塞尔曲线的绘制,合理利用CanvasRenderingContext2D的translate和rotate等API。

  绘制椭圆

  在模拟水滴之前,我们先思考一下怎么在canvas当中绘制一个椭圆。

  大家可以很容易想到 下面几种方案:

  1.根据椭圆笛卡尔坐标系方程绘制

  2.根据椭圆极坐标方程绘制

  3.根据椭圆曲率变化绘制

  4.利用四条贝塞尔曲线绘制

  第四中,也是性能最好的一种,这样可以避免复杂的计算,充分利用CanvasRenderingContext2D的API(API的性能是通过严格测试,一般情况下比较靠谱).

  所以我们采用第四种方式来绘制椭圆。

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);

  (改变drawEllipse的四个参数试试)

  旋转椭圆

  这里的旋转不是绕上面的drawEllipse的前两个参数x,y旋转,二是绕椭圆的中心旋转。所以仅仅CanvasRenderingContext2D.rotate是不够的,因为CanvasRenderingContext2D.rotate是绕画布的左上角(0,0)旋转。所以我们先要把(0,0)通过CanvasRenderingContext2D.translate到椭圆的中心,然后再drawEllipse(-a/2, –b/2, a, b).

  上面这句话,就是绕中心旋转的核心。这里还可以推广到任意图形或者图片(假设有约定的中心)。如图: