Анимация HTML-элементов холста - PullRequest
0 голосов
/ 02 декабря 2011

Я пытаюсь анимировать элементы на <canvas>, но setTimeout и setInterval вызывают у меня проблемы.Мои данные в массиве.Я получаю его длину.Для каждого узла я генерирую X и Y, основное направление и цвет.Затем моя функция рисования рисует круг для каждого из этих узлов.

Мои проблемы возникают, когда я пытаюсь выполнить цикл с помощью setInterval.Я думал, что смогу установить все значения X, Y, а затем вернуться назад и увеличивать их каждые 10-100 мс.Но каждый раз, когда я использую setInterval, мои дочерние массивы, которые содержат данные для каждого круга, получают длину 3, а значения устанавливаются как неопределенные.

Я однажды кодировал это, используя различные объекты, но не смог заставить анимацию работать.Я узнал о проблемах с областью видимости 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();
    }
}

1 Ответ

2 голосов
/ 02 декабря 2011

Я не знаю, является ли это единственной проблемой в вашем коде, но одной существенной проблемой является то, как вы используете setTimeout():

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

То есть, для вызова функции plotXY()и затем передайте все, что возвращается в качестве первого параметра, setTimeout.

Вместо этого первый параметр в setTimeout() должен быть выражением функции или ссылкой на такую ​​функцию:

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

Обратите внимание, что plotXY имеет не для этой цели есть скобки.Но, конечно, это оставляет вас с другой проблемой: вы хотите, чтобы plotXY() вызывался с параметром true.Это легко решить, обернув вызов plotXY() в другой функции и передав эту функцию в setTimeout():

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

, которая создает анонимную функцию и передает эту функцию setTimeout().

Возможно, вы захотите снова вызвать setTimeout() в конце вашей функции plotXY() или использовать setInterval(), иначе ваша анимация будет иметь только один шаг.Или вы можете сделать что-то вроде следующего, который показывает и другой способ решения проблемы передачи параметров и способ продолжать вызывать функцию с помощью setTimeout():

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

Конечно, вы можете добавить некоторую условную обработкув пределах plotXYProxy(), чтобы решить, устанавливать ли каждый тайм-аут, например, вы могли бы plotXY() вернуть логическое значение относительно того, закончилась ли анимация, и вызвать setTimeout() или нет, основываясь на этом логическом значении.Или что угодно.

Все, что я только что сказал о параметрах setTimeout(), также относится к setInterval().

...