依照指定的時間執行動作or動畫效果

 Tue, 13 Jan 2009 15:53:50 +0800

期末報告的季節又到了...

看到有人在論壇上求助,html的作業要求做出配合音樂節拍播放圖片......(嗯嗯,對於初學者來說,恐怕有點難),有一點好奇,所以手動試了一下,怎麼做出依照給定時間執行動作的效果。

以下是程式:

<html>
<body>
<div id="panel"><img src="bg/char1.gif"></div>
<script>
(function(){
    var component = {
        target: null,
        init: function(x) {this.target = x; return this;},
        click: function(f) {this.target.onclick = f; return this;},
        html: function(t) {this.target.innerHTML = t; return this;},
        actionSequencer: function(t) {
            var target = this.target;
            var duration = t.duration|0;
            var action = t.action|[];
            action = t.action.sort(function(a,b){return a[0]-b[0];});
            var drop = t.drop|false;
            var start;
            var curr = start = new Date().getTime();
            var timer = true;
            var currTimeUpdater = window.setInterval(function(){
                if(timer) {
                    curr = new Date().getTime();
                } else {
                    window.clearInterval(currTimeUpdater);
                }
            },1);
            var timerStop = window.setInterval(function(){
                if ((curr - start) > duration) {
                    timer = false;
                    window.clearInterval(timerStop);
                }
            },1);
            var actionHandler = window.setInterval(function(){
                if(timer) {
                    if(action.length>0&&(curr-start) > action[0][0]) {
                        if(!drop) {
                            var a = window.setTimeout(function(){
                                window.clearTimeout(a);
                                action[0][1](target);
                                action.shift();
                                },
                            1);
                        } else {
                            for(var i=0; i<action.length; i++) {
                                if(action[i][0] > curr-start) {
                                    var b = window.setTimeout((function(j){
                                        window.clearTimeout(b);
                                        return function(){
                                            action[j][1](target);
                                        };})(i),1);
                                    return;
                                }
                            }
                        }
                    }
                } else {
                    window.clearInterval(actionHandler);
                }
            },1);
            return this;
        }
    };
    $ = function(x) {
        return component.init(x);
    };
})();
$(document.getElementById("panel")).click(function(){
    $(this).actionSequencer(
    {
        duration: 1000,
        action: [
            [100, function(target){$(target).html('<img src="bg/char1.gif">');}],
            [200, function(target){$(target).html('<img src="bg/char2.gif">');}],
            [300, function(target){$(target).html('<img src="bg/char3.gif">');}],
            [400, function(target){$(target).html('<img src="bg/char5.gif">');}],
            [500, function(target){$(target).html('<img src="bg/char4.gif">');}],
            [600, function(target){$(target).html('<img src="bg/char6.gif">');}],
            [700, function(target){$(target).html('<img src="bg/char7.gif">');}],
            [800, function(target){$(target).html('<img src="bg/char8.gif">');}],
            [900, function(target){$(target).html('<img src="bg/char1.gif">');}]
        ],
        drop: false
    });
});
</script>
</body>
</html>

 

有興趣的話,可以到這裡看一下效果,另外還有高速版(動作比較快,測試瀏覽器可以動作的時間最小單位的極限),請看這裡

有一點懶得解釋程式,簡單地說,就是盡量用setInterval跟setTimeout來讓執行的動作不影響計時與控制,所以可以在比較精確的時間執行動作。另外,也用最簡單的方式模仿jQuery的coding style,哈哈。(當然,沒有selector)

另外,稍微解釋傳給actionSequencer的參數:

  1. duration: 總共時間
  2. action:陣列,每個元素還是一個陣列,指定要執行動作的時間及執行的動作。系統會傳給動作函數一個target的參數用來指定效果要在哪個元素上執行。
  3. drop: 用不一樣的方法來執行動作,在指定動作的時間間隔較短時可能會發生作用,在來不及執行動作時就不執行,直接執行下一個動作。這個方法我還沒做很詳細的驗證。