記錄13 畫布動畫

用 JavaScript 創建畫布動畫,是創建一個定格圖案,擦除該圖案, 然后在一個新的位置重新繪制它。這聽上去有很多個步驟,但是, JavaScript 可以很快地更新圖形的位置,以創建一個平滑的動畫。

我們使用畫布和 setInterval 來繪制一個方塊,并且讓其緩慢地在頁面上移動

  • 調用了 clearRect,它在畫布上清除出一個矩形區域。
    因為方塊移動范圍是在畫布里面,所以我們清除的區域是200*200,這樣無論方塊此時移動到哪里都會被清除。

  • 間隔為30毫秒,在(0,0)處畫一個2020的方塊,然后清除區域內容;在(1,0)處畫一個2020的方塊,然后清除區域內容;然后在(2,0)處畫。。。。,因為過程很平滑,所以看起來就像看動畫一樣。超出畫布范圍后回到左側重新開始移動。

<body>
    <canvas id="canvas" width="200" height="200"></canvas>>
    <script type="text/javascript" src="jquery-3.1.1.js"></script>
    <script type="text/javascript">
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var position = 0;
        setInterval(function(){
            ctx.clearRect(0,0,200,200);
            ctx.fillRect(position,0,20,20);
            position++;
            if(position > 200){
                position = 0;
            }
        },30);
    </script>
</body>

注意ctx.fillRect(position,0,20,20);必須放在后面,不然每次都是一執行繪制方法馬上執行清除方法,頁面始終空白。而先清除,再繪制之后,間隔30毫秒才開始繼續清除、繪制,這樣才能達到動畫效果。

方塊大小變化的動畫

<body>
    <canvas id="canvas" width="200" height="200"></canvas>
    <script type="text/javascript" src="jquery-3.1.1.js"></script>
    <script type="text/javascript">
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
        var size = 0;
        setInterval(function(){
            ctx.clearRect(0,0,200,200);
            ctx.fillRect(0,0,size,size);
            size++;
            if(size > 200){
                size = 0;
            }
        },30);
    </script>
</body>

繪制一個在頁面上亂飛的蜜蜂

1,繪制蜜蜂可以構造多個圓形的組合圖形
2,亂飛就是讓這個組合圖形隨機移動

  • 定義一個circle方法,根據參數 ?llCircle 來繪制實心圓或者圓形邊框。
  • drawBee方法用于調用circle方法繪制出蜜蜂
  • 創建一個update方法來隨機修改米飯的x坐標和y坐標,使得蜜蜂實現在畫布上隨機移動

1,offset 值會給出一個在-2 到 2 之間的隨機值,這是蜜蜂每次隨機移動的距離大小。
2,通過確保coordinate 不會增加到200 以上或者減少 到 0 以下,從而防止蜜蜂離開畫布。如果coordinate 大于200,將其設置回 200;如果 coordinate 小于 0,將其設置回 0。

  • 返回了新的coordinate 值,也就是新的坐標。傳入x坐標會返回新的x坐標,傳入y的坐標會返回新的y坐標(分別傳入是因為x方向移動距離不一定等于y方向的移動距離,體現隨機的不只是移動方向還有移動距離)

coordinate += offset; 的+和=之間不允許有空格,不然報錯one.html:48 Uncaught SyntaxError: Unexpected token =

完整代碼如下:

<body>
    <canvas id="canvas" width="200" height="200"></canvas>
    <script type="text/javascript" src="jquery-3.1.1.js"></script>
    <script type="text/javascript">
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");

        //蜜蜂起始位置
        var x= 100;
        var y= 100;

        var circle = function(x,y,radius,fillCircle){
            ctx.beginPath();
            ctx.arc(x,y,radius,0,Math.PI*2,false);
            if(fillCircle){
                ctx.fill();  //畫出實心圓
            }else{
                ctx.stroke();  //畫出圓形邊框
            }
        };

        //繪制蜜蜂
        var drawBee = function(x,y){
            ctx.lineWidth = 2;
            ctx.strokeStyle = "Black";
            ctx.fillStyle = "Gold";

            //調用上面的circle函數,最后一個參數對應上面定義的fillCircle參數
            //第一個圓是實心圓,代表蜜蜂身體
            circle(x,y,8,true);
            //在蜜蜂身體繪制一個黑色的圓邊框
            circle(x,y,8,false);
            //在身體上繪制黑色邊框的翅膀
            circle(x-5,y-11,5,false); 
            circle(x+5,y-11,5,false);
            //在最上方繪制兩個眼睛
            circle(x-2,y-1,2,false);
            circle(x+2,y-1,2,false);
        }

        var update = function(coordinate) {
            var offset = Math.random()*4 - 2;
            // coordinate + = offset; 錯誤
            coordinate += offset; 
            if(coordinate > 200){
                coordinate = 200;
            }
            if(coordinate < 0){
                coordinate = 0;
            }
            return coordinate;
        };

        setInterval(function(){
            ctx.clearRect(0,0,200,200);
            drawBee(x,y);
            x=update(x);
            y=update(y);
            ctx.strokeRect(0,0,200,200);
        },30);

    </script>
</body>

效果圖如下:


Paste_Image.png

彈跳的球(帶有速度和方向)

現在,我們來制作在畫布上彈跳的球。無論何時,當球碰到墻的時候, 它都會以一個角度彈回,就像是一個橡皮球一樣

開始位置設置在(100,100),this.xSpeed設置為-2將會在動畫的每一步中將球向左移動2個像素。 this.ySpeed設置為3使得球在每一個動畫步驟中向下移動3個像素。因此, 在每一幀之間,球將會斜著向下移動(3 個像素)并向左移動(2 個像素)。


Paste_Image.png
  • 向Ball原型添加draw方法繪制球,以便Ball構造方法創建的任何實例都能夠使用它

  • 彈跳球,我們檢查球是否碰到一面墻。如果是,通過將xSpeed屬性或ySpeed 屬性取反(將其與-1 相乘)而更新它們。例如,如果球碰到了底部的墻,將this.ySpeed取反。因此,如果this.ySpeed是3,取反后將其變為-3。如果 this.ySpeed是-3,取反后將其設置為3。


完整代碼如下:

<body>
    <canvas id="canvas" width="200" height="200"></canvas>
    <script type="text/javascript" src="jquery-3.1.1.js"></script>
    <script type="text/javascript">
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");

        //球的屬性,包括位置坐標和速度
        var Ball = function(){
            this.x=100;
            this.y=100;
            this.xSpeed = -2;
            this.ySpeed = 3;
        }

        //向Ball原型添加draw方法繪制球,以便Ball構造方法創建的任何實例都能夠使用它
        var circle = function (x,y,radius,fillCircle){
            ctx.beginPath();
            ctx.arc(x,y,radius,0,Math.PI*2,false);
            if(fillCircle){
                ctx.fill();
            }else{
                ctx.stroke();
            }
        };
        Ball.prototype.draw = function(){
            circle(this.x,this.y,3,true);
        };

        //移動球,就是根據速度改變球的坐標屬性值
        Ball.prototype.move = function(){
            this.x += this.xSpeed;
            this.y += this.ySpeed;
        };

        //檢查球是否會與墻碰撞,如果球移動到畫布邊界,
        //水平到達邊界,讓x方向速速度取反
        //豎直達到邊界,讓y方向速度取反
        Ball.prototype.checkCollision = function() {
            if(this.x < 0 || this.x > 200 ){
                this.xSpeed = -this.xSpeed;
            }
            if(this.y < 0 || this.y > 200 ){
                this.ySpeed = -this.ySpeed;
            }
        }

        //實現球的動畫
        var ball = new Ball();
        setInterval(function(){
            //清除畫布
            ctx.clearRect(0,0,200,200);
            //繪制球體,與上面清除畫布的間歇性配合平滑檫除重新繪制,達到動畫效果
            ball.draw();
            ball.move();
            ball.checkCollision();
            //繪制墻,就是邊框,與clearRect沒有任何關系
            ctx.strokeRect(0,0,200,200);
        },30);

    </script>
</body>

效果圖如下

Paste_Image.png
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容