2011-12-01 215 views
0

我試圖在<canvas>上設置動畫元素,但setTimeout和setInterval給我的問題。我的數據在一個數組中。我得到它的長度。對於每個節點,我生成一個X和一個Y,一個基本方向和一個顏色。然後我的繪圖函數爲每個節點繪製一個圓。動畫HTML畫布元素

當我嘗試使用setInterval進行循環時,出現了問題。我的想法是,我可以建立所有的X,Y值,然後循環回來,每10ms-100ms增加一次。但每次我使用setInterval時,我的子數組中的每個圓圈的數據長度都是3,並且這些值設置爲undefined。

我使用各種對象編碼一次,但無法使動畫工作。我瞭解了在對象中使用範圍setInterval()的問題。我沒有建立一堆物體就重新編寫了它。仍然沒有運氣。

$(document).ready(function(){ 
    getTweets(); 
}); 

CTX = $('#tweets')[0].getContext("2d"); 
WIDTH = $('#tweets').width(); 
HEIGHT = $('#tweets').height(); 
RADIUS = 10; 
TWEETS = []; 
CORDS = []; 
DIRECTION = ['north','east','south','west']; 

function getTweets(){ 
    $.getJSON("http://search.twitter.com/search.json?callback=?&q=scion&rpp=100", 
    function(r){ 
     var numberOfTweets = r.results.length; 
     while(numberOfTweets--){ 
      TWEETS.push(r.results[numberOfTweets].text); 
     } 
     plotXY(); 
     animateTweets() 
    }); 
} 

function animateTweets(){ 
    return setTimeout(plotXY(true),100); 
} 

function plotXY(animating){ 
    if(!animating){ 
     var numberOfTweets = TWEETS.length; 
     while(numberOfTweets--){ 
      var topY = Math.ceil(Math.random()*(HEIGHT-20)), 
       leftX = Math.ceil(Math.random()*(WIDTH-20)), 
       cardinal = Math.floor(Math.random()*4), 
       color = '#'+Math.floor(Math.random()*16777215).toString(16); 

      var valCords = validateCords(leftX, topY); 
      CORDS.push([valCords[0], valCords[1], cardinal, color]); 
     } 
     // console.log('animating false'); 
     // console.log(CORDS); 
    } 
    else{ 
     var numberOfTweets = TWEETS.length; 
     while(numberOfTweets--){ 
      if(CORDS[numberOfTweets][2]=='north'){ //NORTH 
       CORDS[numberOfTweets][1]+=2; 
       CORDS[numberOfTweets][0]+=2; 
      } 
      if(CORDS[numberOfTweets][2]=='east'){ //EAST 
       CORDS[numberOfTweets][1]+=2; 
       CORDS[numberOfTweets][0]-=2; 
      } 
      if(CORDS[numberOfTweets][2]=='south'){ //SOUTH 
       CORDS[numberOfTweets][1]-=2; 
       CORDS[numberOfTweets][0]-=2; 
      } 
      if(CORDS[numberOfTweets][2]=='west'){ //WEST 
       CORDS[numberOfTweets][1]-=2; 
       CORDS[numberOfTweets][0]+=2; 
      } 

      var valCords = validateCords(leftX, topY, numberOfTweets); 

      CORDS.push([valCords[0],valCords[1],cardinal]); 
      CORDS.shift();   
     } 
     // console.log('animating true'); 
     // console.log(CORDS); 
    } 
    drawCircles(); 
} 


function drawCircles(){ 
    console.log('drawing'); 
    var numOfCords = CORDS.length; 
    clear(); 

    while(numOfCords--){ 
     CTX.fillStyle = CORDS[numOfCords][3]; 
     CTX.beginPath(); 
     CTX.arc(CORDS[numOfCords][0], CORDS[numOfCords][1], RADIUS, 0, Math.PI*2, true); 
     CTX.closePath(); 
     CTX.fill(); 
    } 
} 
+0

你是否將數組存儲在像窗口對象這樣的持久位置? – Ian

+0

這是一個問題:'setTimeout(plotXY(true),100);' - 調用'plotXY(true)',然後將結果傳遞給'setTimeout'。你需要做的是傳遞一個函數的引用,最簡單的方法就是這樣:'setTimeout(function(){plotXY(true);},100);'(同樣適用於'setInterval() '。您可能想要爲'plotXY()'函數的結尾再次調用'setTimeout()',或者使用'setInterval()',否則您的動畫只會有一個步驟。 (注意:如果你的函數沒有任何參數,你可以像這樣直接傳遞它:'setTimeout(plotXY,100)'。) – nnnnnn

+0

@nnnnnn謝謝你指出我的格式錯誤。我有setInterval,但用setTimeout取代它,看看它是否只是定時功能的問題。我認爲這是基於你的建議。我現在必須做出改變,但我認爲它可能解決了我的問題。 – Andalinmicphew

回答

2

我不知道這是不是在你的代碼的唯一問題,而是一個顯著的問題是您正在使用setTimeout()方式:

setTimeout(plotXY(true), 100); // doesn't work 

,說打電話給plotXY()功能,然後把它返回的第一個參數傳遞給setTimeout

相反,爲了setTimeout()第一參數應該是一個函數式或參照一個功能是這樣的:

setTimeout(plotXY, 100);  // works, but doesn't pass parameter to plotXY() 

注意plotXY確實具有用於此目的的括號。但是,當然這會給您帶來另一個問題:您需要使用參數true調用plotXY()。這是很容易在另一個函數包裝調用plotXY()和通過其他功能setTimeout()解決:

setTimeout(function(){ plotXY(true); }, 100);  // works 

這將創建一個匿名函數並傳遞功能setTimeout()

您可能想要在plotXY()函數結束時再次撥打setTimeout(),或者使用setInterval(),否則您的動畫將只有一個步驟。或者你可以不喜歡以下,其中顯示,無論另一種方式來解決參數傳遞問題,並以此來保持通話與setTimeout()功能:

function plotXYProxy() { 
    plotXY(true); 
    setTimeout(plotXYProxy, 100); 
} 
plotXYProxy(); 

當然,你可以在plotXYProxy()添加一些有條件的處理決定是否設置每個超時,例如,您可以讓plotXY()返回布爾值,以確定動畫是否已完成,並根據該布爾值調用setTimeout()。或者任何適合。

我剛纔所說的關於setTimeout()的參數也適用於setInterval()