Pregunta

Estoy tratando de animar elementos en el <canvas> Pero SetTimeout y SetInterval me están dando problemas. Mis datos están en una matriz. Tengo su longitud. Para cada nodo genero una x y una y, una dirección cardinal y un color. Entonces mi función de dibujo dibuja un círculo para cada uno de esos nodos.

Mis problemas surgen cuando intento enojarme con un SetInterval. Mi pensamiento era que podía establecer todos los valores X, Y, luego recurrirlos e incrementarlos cada 10 ms-100 ms. Pero cada vez que uso SetInterval My Child Arrays que contienen los datos para cada círculo obtienen una longitud de 3 y los valores están configurados en indefinido.

Codé esto una vez usando varios objetos, pero no pude hacer que funcionara la animación. Aprendí sobre los problemas con el alcance setInterval () en objetos. Lo recodé sin establecer un montón de objetos. Todavía no hay suerte.

$(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();
    }
}
¿Fue útil?

Solución

No sé si este es el único problema en su código, pero un problema importante es la forma en que está utilizando setTimeout():

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

Que dice llamar al plotXY() función y luego pasar lo que devuelva como el primer parámetro para setTimeout.

En cambio, el primer parámetro a setTimeout() debe ser una expresión de función o referencia a una función como esta:

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

Tenga en cuenta que plotXY lo hace no tener paréntesis para este propósito. Pero, por supuesto, eso te deja con otro problema: quieres plotXY() para ser llamado con el parámetro true. Que se resuelve fácilmente envolviendo la llamada a plotXY() en otra función y pasar esa otra función a setTimeout():

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

Que crea una función anónima y pasa esa función a setTimeout().

Probablemente quieras llamar setTimeout() de nuevo al final de tu plotXY() función o uso setInterval(), de lo contrario, su animación solo tendrá un paso. O puede hacer algo como lo siguiente, que muestra otra forma de resolver el problema de aprobación de los parámetros y una forma de seguir llamando a la función con setTimeout():

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

Por supuesto, puede agregar un procesamiento condicional dentro plotXYProxy() Para decidir si establecer cada tiempo de espera, por ejemplo, podría tener plotXY() devolver un booleano sobre si la animación ha terminado y llamado setTimeout() o no basado en ese booleano. O lo que sea que se adapte.

Todo lo que acabo de decir sobre los parámetros de setTimeout() también se aplica a setInterval().

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top