canvas 模擬地球繞太陽轉動 月球繞地球轉動

requestAnimationFrame,Web中寫動畫的另一種選擇

HTML5/CSS3時代,我們要在web裏做動畫選擇其實已經很多了:

你可以用CSS3的animattion+keyframes;

你也可以用css3的transition;

你還可以用通過在canvas上作圖來實現動畫,也可以藉助jQuery動畫相關的API方便地實現;

當然最原始的你還可以使用window.setTimout()或者window.setInterval()通過不斷更新元素的狀態位置等來實現動畫,前提是畫面的更新頻率要達到每秒60次才能讓肉眼看到流暢的動畫效果。

現在又多了一種實現動畫的方案,那就是還在草案當中的window.requestAnimationFrame()方法。

window.requestAnimationFrame方法

來看MDN上對其給出的詮釋:
window.requestAnimationFrame() 將告知瀏覽器你馬上要開始動畫效果了,後者需要在下次動畫前調用相應方法來更新畫面。這個方法就是傳遞給window.requestAnimationFrame()的回調函數。

也可這個方法原理其實也就跟setTimeout/setInterval差不多,通過遞歸調用同一方法來不斷更新畫面以達到動起來的效果,但它優於setTimeout/setInterval的地方在於它是由瀏覽器專門爲動畫提供的API,在運行時瀏覽器會自動優化方法的調用,並且如果頁面不是激活狀態下的話,動畫會自動暫停,有效節省了CPU開銷。

基本語法

可以直接調用,也可以通過window來調用,接收一個函數作爲回調,返回一個ID值,通過把這個ID值傳給window.cancelAnimationFrame()可以取消該次動畫。

window.requestAnimationFrame(move);//move爲回調函數

arc()方法:

arc(x,y,radius,x1,y2,false) 六個參數 x,y 圓心的座標 , radius 圓的半徑,x1爲其實弧度,y1爲終止弧度,如果畫圓 x1 = 0,y1 = 2*Math.PI, 最後一個參數畫圓的方向,有兩個值 false (順時針)和 true (逆時針)。

clearRect() 方法:

clearRect(x,y,w,h) 四個參數 x,y 爲要清除位置的起始座標, w,h 爲要清除的寬高

開始畫圓

畫太陽,地球,月球的過程都是用 canvas 畫圓,因爲它們除了 圓心座標和半徑不一樣以爲 ,其他過程都是一樣的,所以我將畫圓的方法封裝起來,在畫的時候給不同的參數來調用這個類

封裝類

function Point(x,y){
this.x = x; //圓心的 X 座標
this.y = y; //圓心的 Y 座標
}

function Circle(origin,radius,speed){
this.origin = origin;  //圓心
this.radius = radius;  //半徑
this.speed = speed;   //轉動速度
this.draw = drawCircle; //畫圓的方法
}

function drawCircle(){
con.beginPath();  //開始繪製
con.arc(this.origin.x,this.origin.y,this.radius,0,2*Math.PI,false); //繪製圓
con.stroke();   //繪製的框
con.closePath();  //繪製結束
}

畫太陽,地球,月亮

這裏只需要調用前面封裝好的類,傳入參數即可

//畫太陽
var sun = new Circle(new Point(400,300),30,0);
sun.draw();
//畫地球軌跡
var earthPath = new Circle(sun.origin,200,0);
earthPath.draw();
//畫地球
var earth = new Circle(new Point(earthPath.origin.x + earthPath.radius, earthPath.origin.y),20,0);
earth.draw();
//畫月亮軌跡
var moonPath = new Circle(earth.origin,80,0);
moonPath.draw();
//畫月亮
var moon = new Circle(new Point(moonPath.origin.x + moonPath.radius, moonPath.origin.y),10,0);
moon.draw();

讓地球和月亮轉動起來

function move(){
    con.clearRect(0,0,canvas.width,canvas.height);


    sun.draw();
    earthPath.draw();
    moonPath.draw();
    earth.draw();
    moon.draw();

    earth.origin.x = earthPath.origin.x + earthPath.radius * Math.cos(earth.speed);
    earth.origin.y = earthPath.origin.y + earthPath.radius * Math.sin(earth.speed);
    earth.speed += 0.02;

    moon.origin.x = moonPath.origin.x + moonPath.radius * Math.cos(moon.speed);
    moon.origin.y = moonPath.origin.y + moonPath.radius * Math.sin(moon.speed);
    moon.speed += -0.05;

    window.requestAnimationFrame(move);
}
    move();

效果圖:

畫面雖然簡單了點 ,但轉動的效果還是可以看見的

這裏寫圖片描述

完整代碼:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <style type="text/css">
            canvas {border: 1px solid black;}
        </style>
    </head>
    <body>
        <canvas id="myCanvas" width="800" height="600"></canvas>
    </body>
    <script type="text/javascript">
        var canvas = document.getElementById('myCanvas');
        var con = canvas.getContext('2d');


        function Point(x,y){
            this.x = x; //圓心的 X 座標
            this.y = y; //圓心的 Y 座標
        }

        function Circle(origin,radius,speed){
            this.origin = origin;  //圓心
            this.radius = radius;  //半徑
            this.speed = speed;   //轉動速度
            this.draw = drawCircle; //畫圓的方法
        }

        function drawCircle(){
            con.beginPath();  //開始繪製
            con.arc(this.origin.x,this.origin.y,this.radius,0,2*Math.PI,false); //繪製圓
            con.stroke();   //繪製的框
            con.closePath();  //繪製結束
        }
        //畫太陽
        var sun = new Circle(new Point(400,300),30,0);
        sun.draw();
        //畫地球軌跡0
        var earthPath = new Circle(sun.origin,200,0);
        earthPath.draw();
        //畫地球
        var earth = new Circle(new Point(earthPath.origin.x + earthPath.radius, earthPath.origin.y),20,0);
        earth.draw();
        //畫月亮軌跡
        var moonPath = new Circle(earth.origin,80,0);
        moonPath.draw();
        //畫月亮
        var moon = new Circle(new Point(moonPath.origin.x + moonPath.radius, moonPath.origin.y),10,0);
        moon.draw();

        function move(){
            con.clearRect(0,0,canvas.width,canvas.height);


            sun.draw();
            earthPath.draw();
            moonPath.draw();
            earth.draw();
            moon.draw();

            earth.origin.x = earthPath.origin.x + earthPath.radius * Math.cos(earth.speed);
            earth.origin.y = earthPath.origin.y + earthPath.radius * Math.sin(earth.speed);
            earth.speed += 0.02;

            moon.origin.x = moonPath.origin.x + moonPath.radius * Math.cos(moon.speed);
            moon.origin.y = moonPath.origin.y + moonPath.radius * Math.sin(moon.speed);
            moon.speed += -0.05;

            window.requestAnimationFrame(move);
        }
        move();

    </script>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章