Domanda

Sto cercando di animare elementi sulla <canvas> ma setTimeout e setInterval mi stanno dando problemi. I miei dati sono in un array. Ottengo la sua lunghezza. Per ogni nodo a generare una X e Y, una direzione cardinale e un colore. Poi la mia funzione di disegno disegna un cerchio per ognuno di questi nodi.

I miei problemi sorgono quando provo e ciclo con un setInterval. Il mio pensiero è stato che ho potuto stabilire tutti i valori X, Y, poi loop back e incrementare loro ogni 10ms-100ms. Ma ogni volta che uso setInterval miei Array bambino che contengono i dati per ogni cerchio ottenere una lunghezza di 3 ed i valori sono impostati su undefined.

ho codificato questa volta utilizzando vari oggetti, ma non ha potuto ottenere l'animazione al lavoro. Ho imparato a conoscere i problemi con scoping setInterval () negli oggetti. Ho ricodificato senza stabilire un gruppo di oggetti. ancora senza fortuna.

$(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();
    }
}
È stato utile?

Soluzione

Non so se questo è l'unico problema nel codice, ma un problema significativo è il modo in cui si sta utilizzando setTimeout():

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

che dice di chiamare la funzione plotXY() e quindi passare qualunque essa ritorna come primo parametro a setTimeout.

Invece, il primo parametro di setTimeout() dovrebbe essere un'espressione funzione o il riferimento a una funzione come questa:

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

Si noti che plotXY non hanno parentesi per questo scopo. Ma, naturalmente, che ti lascia con un altro problema: si vuole plotXY() di essere chiamato con il parametro true. Che è facilmente risolvibile avvolgendo la chiamata a plotXY() in un'altra funzione e passando quell'altra funzione setTimeout():

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

Questo crea una funzione anonima e passa quella funzione di setTimeout().

Probabilmente voler chiamare setTimeout() di nuovo alla fine della funzione plotXY(), o l'uso setInterval(), in caso contrario l'animazione avrà solo un passo. Oppure si può fare qualcosa di simile al seguente, che mostra sia un altro modo per risolvere il problema dei parametri di passaggio e un modo per tenere chiamando la funzione con setTimeout():

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

Naturalmente è possibile aggiungere un po 'di elaborazione condizionale all'interno plotXYProxy() per decidere se impostare ogni timeout, per esempio, si potrebbe avere plotXY() ritorno un valore booleano sul fatto che l'animazione ha finito e chiamata setTimeout() o meno sulla base di tale booleano. O qualunque abiti.

Tutto quello che ho appena detto sui parametri di setTimeout() vale anche per setInterval().

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top