2010-03-12 3 views
1

У меня есть страница, которая содержит несколько элементов <canvas>.Как запустить setInterval() на нескольких холстах одновременно?

Я передаю идентификатор холста и массив данных функции, которая затем захватывает информацию о холсте и передает данные функции draw(), которая, в свою очередь, обрабатывает данные и выводит результаты на холст. Все идет нормально.

Примеры массивов данных;

$(function() { 
    setup($("#canvas-1"), [[110,110,100], 
          [180,180,50], 
          [220,280,80]]); 

    setup($("#canvas-2"), [[110,110,100], 
          [180,180,50], 
          [220,280,80]]); 
}); 

установка функция;

function setup(canvas, data) { 
    ctx = canvas[0].getContext('2d'); 
    var i = data.length; 
    var dimensions = { 
     w : canvas.innerWidth(), 
     h : canvas.innerHeight()  
    }; 
    draw(dimensions, data, i); 
} 

Это прекрасно работает. draw() работает, и каждый холст заполнен.

Однако - мне нужно анимировать холст. Как только я заменю строку 8 вышеприведенного примера;

draw(dimensions, data, i); 

с

setInterval(function() { draw(dimensions, data, i); }, 33); 

Он перестает работать, и только рисует последний холст (с остальными оставшимся пустыми).

Я новичок и на javascript, и на холсте, так что извините, если это очевидно, все еще чувствуя мой путь. Руководство в правильном направлении высоко ценится! Благодарю.

+2

Не будучи экспертом по холсту, мне кажется, что глобальный ctx может быть виновником. – HBP

ответ

3

Проблемы связана с how closures work. Закрытие не получает копии данных, они получают активную ссылку . Поэтому, когда функция запускается позже, она ссылается на живую копию из i и такие, которые были перемещены с момента установки вызова.

Вы можете исправить это следующим образом:

drawLater(dimensions, data, i); 

... с этим определены в другом месте:

function drawLater(dimensions, data, i) { 

    setInterval(function() { draw(dimensions, data, i); }, 33); 
} 

Это работает, потому что закрытие содержит ссылку на аргументы в drawLater, а не переменные в вашем цикле.

Отдельно: Разве вы не должны проходить мимо холста или его идентификатора где-то?

+1

Спасибо - действительно, мне нужно наградить 3 принятых ответа здесь, потому что все помогли :) – Alex

-2

Я думаю, что вы должны быть в состоянии сделать его работу, если вы выполните следующие действия:

setInterval('draw(dimensions, data, i);', 33); 

Надеется, что это помогает :)

+2

Избегайте всех форм 'eval', включая неявные оценки, когда это возможно. И это почти всегда возможно. Я также не думаю, что это сработает, отдельно от eval. –

+1

Это все равно не получится, потому что вы используете 'eval' вне текущей области, поэтому переменные будут недоступны. –

2

Как draw() знаете, какой холст использовать? Мое предположение из вашего кода заключается в том, что вы используете глобальную переменную ctx, которая будет перезаписана при каждом вызове setup(). Поэтому вам нужно изменить draw() и добавить холст для использования в качестве первого параметра.

1

Переменные JavaScript: function scoped, а не блокированные области. Также вам нужно объявить ctx с var, чтобы сделать его локальным, а затем передать его функции рисования.

+0

Спасибо, это было очень полезно для моего понимания того, что на самом деле происходит не так. ctx был глобальным, был явным надзором, который работал только до точки! – Alex

Смежные вопросы