javascript動畫總結(一)

前言:其實js動畫跟CSS-DOM結合的挺緊密的,都是用js函數實現一段時間內重複設置元素的樣式就造成了動畫,其中涉及到大量的用DOM獲取元素樣式操做,因此能夠先看一下CSS-DOM那篇文章,此次總結一下js中的動畫,這一篇是基礎知識總結,只用到了setTimeout函數,還有兩個定時器函數下篇文章總結,最後要實現一個純js輪播圖Demo,好的,黑喂狗javascript

------------------ 你瞅啥? -------------------------html

1.一個Demo

首先想讓一個元素移動要先設置一個元素,假設咱們如今有一標籤:<p id="message">Hello World!!!</p>,咱們能夠在js代碼中設置它的初始位置:position:absolute,設置它距離left和right的距離,以下代碼前端

function positionMessage(){
        //檢測與判斷
        if(!document.getElementById){
            return false;
        }
        if(!document.getElementById("message")){
            return false;
        }
        //獲取元素的標籤
        var elem = document.getElementById("message");
        //設置元素的位置
        elem.style.position = "absolute";
        elem.style.left = "50px";
        elem.style.top = "100px";
    }

接下來咱們介紹一個延遲執行函數,setTimeout(),它接受兩個參數,第一個參數時字符串,內容是將要執行的那個函數名字;第二個參數是一個數值,以毫秒爲單位設定須要通過多長時間後纔開始執行第一個參數裏面的函數。因此有個這個函數,咱們能夠寫一個不斷改變位置的函數moveMessage(),而後把它傳遞給setTimeout()函數。以下代碼:java

function moveMessage(){
        if(!document.getElementById){
            return false;
        }
        if(!document.getElementById("message")){
            return false;
        }
        var elem = document.getElementById("message");
        var xpos = parseInt(elem.style.left);
        var ypos = parseInt(elem.style.top);
        if(xpos ==200&&ypos == 100){
            return true;
        }
        if(xpos  < 200){
            xpos++;
        }
        if(xpos > 200){
            xpos--;
        }
        if(ypos < 100){
            ypos++;
        }
        if(ypos > 100){
            ypos--;
        }
        elem.style.left = xpos + "px";
        elem.style.top = ypos + "px";
        movement = setTimeout("moveMessage()",10);
    }

1.首先獲取原始的left和position值,因爲涉及到不少計算,因此將字符串轉換爲數。
2.進行一些判斷,將目標位置設置在left在200px,top不變,也就是將其向右水平移動。而後進行邏輯判斷:若是到達目標位置,就返回true,函數執行完畢。
3.若是沒有到達位置,則不斷將數值加1,若是超過設定位置則減1.
4.最後在moveMessage()函數內部設置setTimeout()函數,即在moveMessage()函數一次執行結束後,就每隔10毫秒再次調用這個函數,即在剛開始每隔10毫秒向右移動1px,直到到達設定地點函數return true結束整個函數。函數

最後要在頁面加載完成後調用這個函數,因此要用到老朋友addLoadEvent()函數,以下代碼:動畫

function addLoadEvent(func){
        var oldonload = window.onload;
        if(typeof window.onoad != 'function'){
            window.onload = func;
        }else{
            window.onload = function(){
                oldonload();
                func(); 
            }
        }
    }

最後在頁面加載完成時執行moveMessage()函數:編碼

addLoadEvent(PositionMessage);

2.抽象

剛纔建立的moveMessage()函數中有不少信息都是硬編碼在函數中,這個函數的靈活性和適用範圍就小,因此將一些具體的東西抽象出來,則這個函數就更加便於複用。
如今咱們建立一個moveElement()函數,看下面代碼:code

//首先爲這個函數傳進幾個參數
        //@elementID:打算移動的元素的ID
        //@final_x:該元素目的地距左邊的位置
        //@final_y:該元素目的地距上邊的位置
        //@interval:該元素兩次移動之間的停頓時間
        function moveElement(elementID,final_x,final_y,interval){
            //進行檢測和判斷
            if(!document.getElementById){
                return false;
            }
            if(!document.getElementById(elementID)){
                return false;
            }
            var elem = document.getElementById(elementID);  //參數沒有引號
            var xpos =parseInt(elem.style.left);
            var ypos = parseInt(elem.style.top);
            if(xpos == final_x && ypos == final_y){
                return true;
            } 
            if(xpos  < final_x){
                xpos++;
            }
            if(xpos > final_x){
                xpos--;
            }
            if(ypos < final_y){
                ypos++;
            }
            if(ypos > final_y){
                ypos--;
            }
            elem.style.left = xpos + "px";
            elem.style.top = ypos + "px";
            //因爲此次moveElement()函數是帶參數的,因此再次調用這個函數要寫成下面一行。
            //movement = setTimeout("moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")",10);
            //可是這麼寫不簡潔,因此能夠複製給一個變量
            var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
            movement = setTimeout(repeat,interval);
        }

直到如今我終於明白爲何要作一次判斷減減了,由於抽象以後,可能傳入的參數會讓元素向相反的方向移動,這樣就寫可讓函數不管向哪一個方向移動均可以了。htm

抽象以後,能夠在positionMessage的最後直接調用moveElement函數,以下代碼:對象

function positionMessage(){
        //檢測與判斷
        if(!document.getElementById){
            return false;
        }
        if(!document.getElementById("message")){
            return false;
        }
        //獲取元素的標籤
        var elem = document.getElementById("message");
        //設置元素的位置
        elem.style.position = "absolute";
        elem.style.left = "50px";
        elem.style.top = "100px";
        
        //調用移動函數,能夠隨意改變值,以實現不用的動畫效果
        moveElement("message",200,100,10);
    }

3.另外一個抽象

//函數animation傳入四個參數,
//@ele:要進行動畫的DOM對象
//@attr:要改變的屬性
//@ from , to 屬性值從哪一個值到哪一個值

var animation = function(ele, attr, from, to){
    var distance = Math.abs(to - from);
    var stepLength = distance/100;
    var sign = (to - from)/distance;  //表明方向
    var offset = 0;
    //step函數是每觸發的時候改變一下屬性值
    var step = function(){
        var temOffset = offset + stepLength;
        if(temOffset < distance){
            ele.style[attr] = from + temOffset*sign + 'px';
            offset = temOffset;
        }else{
            ele.style[attr] = to + 'px';
            clearInterval(intervalID);
        }
    }
    ele.style[attr] = from + 'px';
    
    //先調用定時器,每10毫秒觸發一次step函數
    var intervalID = setTimeout(step,10);
}

以上是網易前端微專業老師給出的抽象代碼,還介紹了另外兩個函數,將在下一篇中介紹。
另外,完整源代碼中沒用這個抽象函數。

4.完整源代碼

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>example</title>

</head>

<body>
    <p id="message">Hello World!!!</p>

    <script>
        function positionMessage(){
            if(!document.getElementById){
                return false;
            }
            if(!document.getElementById("message")){
                return false;
            }
            var elem = document.getElementById("message");
            elem.style.position = "absolute";
            elem.style.left = "50px";
            elem.style.top = "100px";
            moveElement("message",125,25,20);

        }

        function moveElement(elementID,final_x,final_y,interval){
            if(!document.getElementById){
                return false;
            }
            if(!document.getElementById(elementID)){
                return false;
            }
            var elem = document.getElementById(elementID);
            var xpos =parseInt(elem.style.left);
            var ypos = parseInt(elem.style.top);
            if(xpos == final_x && ypos == final_y){
                return true;
            } 
            if(xpos  < final_x){
                xpos++;
            }
            if(xpos > final_x){
                xpos--;
            }
            if(ypos < final_y){
                ypos++;
            }
            if(ypos > final_y){
                ypos--;
            }
            elem.style.left = xpos + "px";
            elem.style.top = ypos + "px";
            var repeat = "moveElement('"+elementID+"',"+final_x+","+final_y+","+interval+")";
            movement = setTimeout(repeat,interval);
        }

        //頁面加載函數
        function addLoadEvent(func){
            var oldonload = window.onload;
            if(typeof window.onload != 'function'){
                window.onload = func;
            }else{
                window.onload = function(){
                    oldonload();
                    func();
                }
            }
        }

        //頁面加載時執行這個函數
        addLoadEvent(positionMessage);

    </script>
</body>

</html>
相關文章
相關標籤/搜索