2016-04-11 53 views
1

我的畫布充當地圖。用戶可以點擊畫布,並在地圖上畫一個標記(畫布)。座標存儲在一個數組中。HTML5畫布時間

當用戶點擊播放按鈕時,畫布會將第一個數組標記繪製到其位置,第二個稍後繪製第二個標記,另一個稍後繪製第三個標記等等。

我怎麼能做到這一點?我試過使用for循環並調用一個setTimeout函數來傳遞我在循環中的值,但是循環變得很快,我無法繞過它。

function timer() { 
    for (i=0; i<array.length; i++){ 
     play(i); 
    } 
} 


    function play(i) { 
    setTimeout(function() { 
    ctx.clearRect(0,0, c.width, c.height); 
    ctx.beginPath(); 
    ctx.moveTo(array[i].x, array[i].y); 
    ctx.lineTo(array[i].x,array[i].y); 
    cursor(array[i].x,array[i].y); 
    }, 1000); 

} 

回答

1

你想設置的時間間隔,並清除間隔當計數器(即在此遞增)達到某一點。例如: -

var t; 
var counter = 0; 
var array = ['your', 'data']; 

function timer() { 
    t = setInterval(play, 1000); 
} 

function play() { 
    if (counter !== array.length) { 
     ctx.clearRect(0,0, c.width, c.height); 
     ctx.beginPath(); 
     ctx.moveTo(array[counter].x, array[counter].y); 
     ctx.lineTo(array[counter].x,array[counter].y); 
     cursor(array[counter].x,array[counter].y); 
     counter++; 
    } else { 
     clearInterval(t); 
     t = null; 
    } 
} 

timer(); // begin calling play() every 1 second for array.length (2 in example) loops 
+0

除了99作爲maxCount以外,這很好。只需拉入數組長度。 :) – zfrisch

+0

setInterval不是一個好辦法,因爲即使先前的滴答沒有完成,它也會打勾。 setTimeout會更好,或者最好是requestAnimationFrame,但用邏輯來處理幀是否應該被處理。如果你使用requestAnimationFrame,那麼如果你移動到不同的標籤,那麼滴答就會停止,有效地讓你的動畫暫停,爲你準備好當你返回到標籤。瀏覽器的時鐘週期也更加高效。 – ManoDestra

1

setTimeout可能不是最好的解決方案。你會更好地使用setInterval來每x毫秒調用一個單獨的函數。你可以粘貼有問題的for循環嗎?

編輯

首先我看到你正在使用的畫布,所以我猜測谷歌地圖API?即使如此,您應該使用requestAnimationFrame進行任何動畫密集型工作。另外,由於工作正在您的播放功能中完成,因此定時器功能幾乎無關緊要。

我有點生疏請requestAnimationFrame我自己,但我認爲這段代碼可能會有所幫助。我認爲setInterval部分會使requestAnimationFrame毫無意義,並且您需要將實際的時間調整到播放函數中。我只是不記得如何去做。

var i = 0; 
 
    
 
    /* 
 
    * change the 1000 to make the animation faster or slower. 
 
    * 1000ms == 1s so 10000 = 10 seconds 
 
    */ 
 
    setInterval(timer(), 1000); 
 

 
    function timer() { 
 
     window.requestAnimationFrame(play); 
 
    } 
 

 
    function play() { 
 
     if (i <= array.length) { 
 
     ctx.clearRect(0, 0, c.width, c.height); 
 
     ctx.beginPath(); 
 
     ctx.moveTo(array[i].x, array[i].y); 
 
     ctx.lineTo(array[i].x, array[i].y); 
 
     cursor(array[i].x, array[i].y); 
 
     i++; 
 
     window.requestAnimationFrame(play); 
 
     } 
 
    }

+0

更新,代碼 –

+0

是的問題,'requestAnimationFrame'是要走的路 - 與硬件更新週期等。此外,英國皇家空軍的最新版本自動發送的時間戳的說法更有效地整合,你可以用來將循環調節到所需的速度。給予好評。 – markE

+1

這真棒,你如何訪問時間戳?它是否附加到您調用它的函數上,還是保存爲窗口變量?編輯:btw感謝我的第一個upvote! :) –

1

使用requestAnimationFrame並將差值存儲在刻度值中,以便您僅在每秒過去後處理更改。

如果您不能使用requestAnimationFrame,則使用setTimeout(play,1000)在1000秒後再次調用播放函數。當然,最後只需增加索引,然後在索引超出範圍之前停止。

不要使用setInterval,因爲這可能會超出您以前的時間間隔的操作。它不會等待完成前一個處理的完成。

E.g.

<script> 
    var lastTick = 0; 
    var elapsed = 0; 
    var index = 0; 
    var array = [4, 5, 6, 7, 8, 9, 10]; 

    function animationLoop(tick) { 
     var diff = tick - lastTick; 
     elapsed += diff; 
     if (elapsed > 1000) { 
      ctx.clearRect(0, 0, c.width, c.height); 
      ctx.beginPath(); 
      ctx.moveTo(array[index].x, array[index].y); 
      ctx.lineTo(array[index].x, array[index].y); 
      cursor(array[index].x, array[index].y); 
      elapsed -= 1000; 
      index++; 
     } 

     if (index < array.length) { 
      lastTick = tick; 
      window.requestAnimationFrame(animationLoop); 
     } 
    } 

    window.requestAnimationFrame(animationLoop); 
</script>