官术网_书友最值得收藏!

實(shí)驗(yàn)3 繪制動(dòng)畫

簡(jiǎn)介

在計(jì)算機(jī)的世界中,有很多東西可以直接看得到,有很多東西已封裝好了,看不到,只能用??吹玫降模罕热?,在實(shí)驗(yàn)2中,設(shè)置小球的顏色和位置,小球的顏色是隨機(jī)產(chǎn)生的,位置是計(jì)算出來的;看不到的:比如,在實(shí)驗(yàn)1中,調(diào)用CanvasRenderingContext2D的beginPath、arc、stroke方法就可以在畫布上畫一個(gè)圓,而看不到各種方法的具體算法和實(shí)現(xiàn),如果不用上述方法,而是自己寫一個(gè)算法去畫一個(gè)圓呢?在自己寫個(gè)畫圓的算法之前,先要了解怎么利用CanvasRenderingContext2D API畫線。

畫線

不用arc方法,自己寫一個(gè)算法來畫圓。在自己寫畫圓的算法之前,首先要了解Canvas RenderingContext2D的moveTo和lineTo方法。

這里需要注意的是HTML DOM Window對(duì)象的moveTo()方法可以把窗口的左上角移動(dòng)到一個(gè)指定的坐標(biāo)。而CanvasRenderingContext2D的moveTo的作用是設(shè)置當(dāng)前位置并開始一條新的子路徑。不能搞混淆了,一個(gè)是window.moveTo,一個(gè)是CanvasRendering Context2D.moveTo。

語(yǔ)法

        moveTo(x,y)

moveTo()方法將當(dāng)前位置設(shè)置為(x,y)并用它作為第一點(diǎn)創(chuàng)建一條新的子路徑。除了moveTo(x,y),還需要知道:

        lineTo(x,y)

lineTo()方法為當(dāng)前子路徑添加一條直線。這條直線從當(dāng)前點(diǎn)開始,到(x,y)結(jié)束。

最后需要用CanvasRenderingContext2D.stroke方法來連接所有路徑。

通過上面這些知識(shí),可以輕松畫出一個(gè)三角形:

        <canvasid="myCanvas"width="200"height="100"style="border:1px solid #c3c3c3;">
        Your browser does not support the canvas element.
        </canvas>
        <scripttype="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>

效果如圖1-14所示。

圖1-14 三角形

另類畫圓

現(xiàn)在回到最開始的問題:如何不通過arc方法來畫一個(gè)圓形?如圖1-15所示,從正三角形到正八邊形,以此類推,正N邊形,當(dāng)N無(wú)限大時(shí),就成為一個(gè)圓形了。根據(jù)這個(gè)原理,畫出一個(gè)圓心在(150,150),半徑為100的圓形。

圖1-15 正N邊形

        <canvasid="myCanvas"width="480"height="300"style="border:1px solid #c3c3c3;">
        Your browser does not support the canvas element.
        </canvas>
        <scripttype="text/javascript">
        var c=document.getElementById("myCanvas");
        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>

其中用到公式:

運(yùn)行效果如圖1-16所示。

圖1-16 圓

但是,明明是在畫圓,怎么沒有看到畫圓的過程呢?JavaScript 就是這樣,解釋完就畫完了,而不會(huì)呈現(xiàn)解釋的過程,這也是為什么 JavaScript不用考慮多線程問題,僅考慮UI線程。那么如何看到畫圓的過程呢?可以使用Jscex來展示畫圓的過程。

注意:在以后的實(shí)驗(yàn)中,如果出現(xiàn)了Jscex.compile,默認(rèn)本實(shí)驗(yàn)已經(jīng)引用了Jscex庫(kù)。

        <scriptsrc="jscex.min.js"type="text/javascript"></script>

這里值得注意的是,大部分實(shí)驗(yàn)都僅僅用到了Jscex的sleep,所以可以輕松改成requestAnimationFrame、settimeout、setinterval的循環(huán)方式,而不使用Jscex,復(fù)雜的線性實(shí)驗(yàn)或者深度嵌套使用Jscex是最佳選擇。

Jscex是“JavaScript Computation Expression”的縮寫,它為JavaScript語(yǔ)言提供了一個(gè)monadic擴(kuò)展。Jscex完全使用JavaScript編寫,能夠在支持ECMAScript 3的任意引擎里使用(如各瀏覽器或Node.js)。Jscex的JIT編譯器能在運(yùn)行時(shí)將JavaScript代碼編譯成Monad形式,無(wú)需額外編譯步驟,并內(nèi)置異步編程類庫(kù),可以大大簡(jiǎn)化JavaScript下的異步編程體驗(yàn)。

倘若不用Jscex,一遇到for循環(huán),就得拆算法,寫回調(diào),破壞程序的可讀性。在使用Jscex來展示畫圓的過程之前,先來看看Jscex經(jīng)常用到的一個(gè)骨架:

        var somethingAsync=eval(Jscex.compile("async", function (a, b) {
        // implementation
            }));

所以下面用這種格式來使用Jscex,并且通過$await(Jscex.Async.sleep(a))使線程停住a/1000秒。

        <canvasid="myCanvas"width="480"height="300"style="border: 1px solid #c3c3c3;">
        Your browser does not support the canvas element.
        </canvas>
        <scriptsrc="../Scripts/jscex.min.js"type="text/javascript"></script>
        <scripttype="text/javascript">
        var c=document.getElementById("myCanvas");
        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));    \注:Sleep一會(huì)兒\
        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));    \注:Sleep一會(huì)兒\
        var tempY=Math.pow(r * r-(x-i) * (x-i), 1 / 2);
                      cxt.lineTo(i, y-tempY);
                      cxt.stroke();
                  }
                }));
                drawAsync().start();
        </script>

現(xiàn)在就可以看到畫圓的整個(gè)過程了,如圖1-17所示。

圖1-17 繪制動(dòng)畫

主站蜘蛛池模板: 新津县| 金湖县| 广宗县| 越西县| 开原市| 南昌市| 安徽省| 古丈县| 崇州市| 和平县| 襄城县| 平江县| 射洪县| 开江县| 华容县| 阿鲁科尔沁旗| 孝义市| 溧阳市| 南宫市| 全州县| 青河县| 宁明县| 四平市| 江陵县| 定日县| 郧西县| 论坛| 延安市| 娄底市| 安塞县| 安泽县| 唐山市| 广丰县| 南充市| 葫芦岛市| 贵州省| 阿尔山市| 汉川市| 房产| 肇州县| 沭阳县|