Html5--绘制动画

 在前两节中,我们都是通过CanvasRenderingContext2D来画圆的,那么我们可不可以自己写个画圆的算法呢?

在这之前,我们先要了解怎么利用CanvasRenderingContext2D API画线?

 

第一步:画线

 

   不用arc方法,自己写一个算法来画圆,在自己写画圆算法之前,首先要了解CanvasRenderingContext2D的moveTo和lineTo方法。

这里需要注意的是html dom window 对象的moveTo()方法可以把窗口的左上角移动到一个指定的坐标。而CanvasRenderingContext2D的moveTo的作用是设置当前位置并开始一条新的子路径。不能搞混淆了,一个是window.moveTo,一个是CanvasRenderingContext2D.moveTo.

    语法:

moveTo(x,y)


moveTo()方法将当前位置设置为(x,y)交用它作为第一点创建一条新的子路径。除了moveTo(x,y),还需要知道:

 

lineTo(x,y)


lineTo()方法为当前子路径添加一条直线,这条直线从当前点开始,到(x,y)结束,最后需要用CanvasRenderingContext2D.stroke方法来连接所有路径。

通过上面这些知识,可以轻松画出一个三角形:

<canvas id="myCanvas" style="width: 200px; height: 100px; border: 1px solid #c3c3c3;">
 你的浏览器不支持canvas
</canvas>
    <script type="text/javascript">
        var c = document.getElementById("myCanvas");
        var cxt = c.getContext("2d");
        cxt.moveTo(20, 10);
        cxt.lineTo(150, 50);
        cxt.lineTo(10, 50);
        cxt.lineTo(20, 10);
        cxt.stroke();
    </script>


运行效果如下:

 

第二步:另类画圆

  现在回到最开始的问题:如何不通过arc方法来画一个圆形?从正三角形到正八边形,以些类推,正N边形,当N无限大时,就成为一个圆形了。根据这个原理,画出一个圆心在(150,150),半径为100的圆形。

 

 <canvas id="myCanvas1" width="480" height="300" style=" border: 1px solid #c3c3c3;">
 你的浏览器不支持canvas
</canvas>
    <script type="text/javascript">
        var c = document.getElementById("myCanvas1");
        var cxt = c.getContext("2d");
        var x = 150;
        var y = 150;
        var r = 100;
        cxt.moveTo(x - r, y);
        for (var i = x - r; i < x + r + 1; i++) {
            var tempY = Math.pow(r * r - (x - i) * (x - i), 1 / 2);
            cxt.lineTo(i, y + tempY);
        }
        cxt.moveTo(x - r, y);
        for (var i = x - r; i < x + r + 1; i++) {
            var tempY = Math.pow(r * r - (x - i) * (x - i), 1 / 2);
            cxt.lineTo(i, y - tempY);
        }
        cxt.stroke();
    </script>


运行效果如下:

但是,明明是在画圆,怎么没有看到画圆的过程呢?JavaScript就是这样,解释完就画完了,而不会呈现解释的过程,这也是为什么JavaScript不用考虑多线程问题,仅考虑UI线程。那么如何看到画圆的过程呢?可以使用Jscex来展示画圆的过程。

 这里值得注意的是,大部分实验仅仅用到了jscex的sleep,所以可以轻松改成requestAnimationFrame、Settimeout、Setinterval的循环方式,而不是使用Jscex,复杂的线性实验或者深度嵌套使用Jscex是最佳选择。

 Jscex是“Javascript Computation Expression” 的缩写,它为Javascript语言提供了一个Monadic扩展。Jscex完全使用Javascript编写,能够在支持Exmascript 3的任意引擎里使用。Jscex的JIT编译器能在运行时将Javascript代码编译成Monad形式,无需额外编译步骤,并内置异步编程类库,可以大大简化Javascript下以异步编程体验。

  倘若不用Jscex,一遇到for循环,就得折算法,写回调,破坏程序的可读性,在使用Jscex来展示画圆的过程之前,先来看看Jscex经常用到的一个骨架:

 var drawAsync = eval(Jscex.compile("async", function () {
//您的代码
              }));


所以下面用这种格式来使用Jscex,并且通过$await(Jscex.Async.sleep(a))使线程停住a/1000秒。

 <canvas id="myCanvas2" width="480" height="300" style="border: 1px solid #c3c3c3;">
 你的浏览器不支持canvas
</canvas>
    <script src="../Scripts/lib/uglifyjs-parser.js" type="text/javascript"></script>
    <script src="../Scripts/src/jscex.js" type="text/javascript"></script>
    <script src="../Scripts/src/jscex.builderBase.js" type="text/javascript"></script>
    <script src="../Scripts/src/jscex.async.js" type="text/javascript"></script>
    <script type="text/javascript">
        var c = document.getElementById("myCanvas2");
        var cxt = c.getContext("2d");
        var x = 150;
        var y = 150;
        var r = 100;
        var drawAsync = eval(Jscex.compile("async", function () {
            cxt.moveTo(x - r, y);
            for (var i = x - r; i < x + r + 1; i++) {
           
                $await(Jscex.Async.sleep(10));
                var tempY = Math.pow(r * r - (x - i) * (x - i), 1 / 2);
                cxt.lineTo(i, y + tempY);
                cxt.stroke();
            }
            cxt.moveTo(x - r, y);
            for (var i = x - r; i < x + r + 1; i++) {
                $await(Jscex.Async.sleep(10));
                var tempY = Math.pow(r * r - (x - i) * (x - i), 1 / 2);
                cxt.lineTo(i, y - tempY);
                cxt.stroke();
            }
        }));
        drawAsync().start();
    </script>


现在就可以看到画圆的整个过程中了。如下图:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值