zoukankan      html  css  js  c++  java
  • 绕中心旋转

    一.简介

    本文告诉读者在Canvas中怎么绕中心旋转,通过此方法模拟出一个2D平面内的水珠,涉及的知识点和技巧包括:Jscex基础知识,贝塞尔曲线的绘制,合理利用CanvasRenderingContext2D的translate和rotate等API。

    image

    二.绘制椭圆

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

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

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

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

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

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

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

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


    (改变drawEllipse的四个参数试试)
    Your browser does not support the canvas element.

    三.旋转椭圆

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

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

    image

    然后我们就可以先绘制一个旋转椭圆出来:


    四.绘制水滴

    旋转的椭圆和鸟巢神马的和水滴有什么关系呢?

    我们通过改变椭圆的长轴和短轴,令其非常接近圆形(只能接近,不能等于圆形),然后每次旋转擦除画布,就可以达你预想不到的效果!

    这里需要注意的是,擦除画布不再是一句CanvasRenderingContext2D.clearRect(0,0,canvas.width,canvas.height)就可以,因为画布已经旋转和画布原点已经translate,所以我们使用 ctx.clearRect(-translate.width, -translate.height, canvas.width, canvas.height)来擦除画布。

    我们画一个长轴42,短轴40的椭圆,旋转并擦除画布:

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

    会是什么效果呢?

    五.在线演示

    Your browser does not support the canvas element.
    现在大家可以看到一个晃动的水珠了。
  • 相关阅读:
    软件开发之需求调研方法论
    系统设计之编码概述
    unix/linux共享库(动态库)简介
    unix/linux静态库简介
    pytest的使用
    c语言中static的作用
    awk文本处理
    shell基本概念
    shell i/o交互及重定向
    shell常用分隔符及管道的用法
  • 原文地址:https://www.cnblogs.com/iamzhanglei/p/2284188.html
Copyright © 2011-2022 走看看