2016-04-11 15 views
1

キャンバスがマップとして動作しています。ユーザーはキャンバスをクリックし、地図(キャンバス)上にマーカーをプロットします。座標は配列に格納されます。HTML5キャンバスのタイミング

ユーザーが再生ボタンをクリックすると、キャンバスは最初の配列マーカーをその位置にプロットし、2番目の後に2番目のマーカーをプロットし、2番目の後に3番目のマーカーをプロットします。

これをどのように達成できますか?私はforループを使用し、ループのiの値を渡す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

maxCountとして99を除いてこれは良いです。配列の長さを引っ張るだけです。 :) – zfrisch

+0

setIntervalはそれを行う良い方法ではありません。以前のティックが完了していなくてもチェックされます。 setTimeoutはより良い、あるいはrequestAnimationFrameであることが望ましいでしょうが、フレームを処理するかどうかを処理するロジックがあります。また、requestAnimationFrameを使用すると、別のタブに移動しても、アニメーションを効果的に一時停止して、タブに戻ったときに準備が整います。ブラウザのクロック・サイクルに比べてはるかに効率的です。 – ManoDestra

1

setTimeoutが最適な解決策ではない可能性があります。 xミリ秒ごとに別々の関数を呼び出すには、setIntervalを使用する方がよいでしょう。問題のforループを貼り付けることはできますか?

編集:すべての

まず、私はあなたがキャンバスを使用していることがわかり、私はGoogleマップAPIを推測していますか?それでも、アニメーションを多用する作業にはrequestAnimationFrameを使用する必要があります。また、あなたの演奏機能で作業が行われているので、タイマー機能は事実上無関係です。

私はrequestAnimationFrame自分で少し錆びていますが、私はこのコードが少し助けてくれると思います。私は、setInterval部分がrequestAnimationFrameを無意味にし、実際のタイミングをplay関数に移す必要があると思います。私はちょうどそれを行う方法を覚えていない。

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'が移動するための方法で更新 - そのより効率的にハードウェアのリフレッシュサイクル、など。また、RAFの最新バージョンが自動的にタイムスタンプ引数に送ると統合していることができますループを所望のペースに絞るために使用します。 Upvote。 – markE

+1

それは素晴らしいです、どうすればそのタイムスタンプにアクセスできますか?それはあなたがそれを呼んでいる関数に付けられるか、それともウィンドウの変数として保存されますか?編集:私の最初のupvoteのbtwありがとう! :) –

1

使用requestAnimationFrameの、目盛り値の差を格納します。

requestAnimationFrameを使用できない場合は、setTimeout(play、1000)を使用して1000秒後にもう一度再生機能を呼び出します。もちろん、最後にインデックスを増やしてから、インデックスを取得する前に停止してください。

setIntervalを使用しないでください。これにより、以前の間隔の操作がオーバーランする可能性があります。前の処理の完了を待つことはありません。

など。

<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> 
関連する問題