2016-04-11 52 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>