Казахстан, Алматы, Гимназия им. Ахмета Байтурсынова №139, 2008 |
Классы и клипы
Ограничения
Функцию watch нельзя использовать для мониторинга полей get / set.
Ни один из приемов, к сожалению, нельзя использовать для мониторинга "стандартных" полей типа _x, _y и пр.
Единственное, что можно предложить для мониторинга значений таких полей, - это setInterval (), но это очень плохой способ, ибо реакцию вы получите с большой задержкой, и, видимо, после перерисовки изображения. Кроме того, значение может успеть измениться к первоначальному значению, пока сработает callback -метод setInterval .
Использование setInterval вместо линейки времени
Иногда для отслеживания времени проще обратиться к программным методам, а не делать дополнительные кадры для того, чтобы узнать, что прошло какое-то время. В таких случаях удобно бывает воспользоваться функцией setInterval , которая обеспечивает вызов нужной нам callback-функции (обработчика) с заданной частотой.
Существует две функции setInterval , первая форма предназначена для вызова методов, которые не обращаются к this, то есть вызова как бы "просто функций", а другая - для вызова методов объектов:
Если пользоваться первой версией setInterval , то в функции function, переданной в качестве параметра setInterval , this будет не определен. Если же пользоваться второй версией setInterval , то он будет ссылаться на объект object, переданный как параметр setInterval .
Обе версии setInterval возвращают так называемый intervalID, который потом нужно передать в функцию clearInterval, чтобы прекратить вызовы callback-функции.
Обратите внимание, что в первом случае передается непосредственно функция, тогда как при использовании второй функции ожидается имя метода, то есть его нужно брать в кавычки.
Interval задается в миллисекундах.
Существуют следующие правила для вызовов setInterval :
- Если параметр interval меньше, чем период обновления клипа (обратная величина частоте кадров), то есть, callback-функция должна вызываться чаще, чем перерисовываются кадры, то флэш-плеер будет стараться вызывать callback-функцию с частотой, возможно более близкой к заданному интервалу. В таком случае нужно вызывать функцию updateAfterEvent в обработчике, чтобы обеспечить достаточно частую перерисовку экрана. Функция updateAfterEvent не имеет параметров, и использовать ее можно только в контексте функции, переданной в качестве обработчика setInterval или в контексте обработчика onClipEvent.
- Если параметр interval больше, чем период обновления клипа (обратная величина частоте кадров), то есть, callback-функция должна вызываться реже, чем перерисовываются кадры, то флэш-плеер будет стараться вызывать callback-функцию в моменты, предшествующие перерисовке новых кадров, чтобы минимизировать количество необходимых перерисовок.
Приведем пару примеров использования setInterval , которые также помогут нам лучше понять механизм работы этой функции.
Пример 1.
N = 10; function code1 () { for (var i = 0; i < N; i++); trace ("code1 invoked"); } function code2 () { for (var i = 0; i < N; i++); trace ("code2 invoked"); } int1 = setInterval (code1, 10); int2 = setInterval (code2, 100);
В данном случае из результатов Output видим, что все работает, как ожидается, то есть обе сallback -функции вызываются с ожидаемой частотой, примерно один вызов второй на 10 вызовов первой.
А теперь попробуем увеличить время, необходимое для выполнения кода функций code1() и code2().
Пример 2.
N = 10000; function code1 () { for (var i = 0; i < N; i++); trace ("code1 invoked"); } function code2 () { for (var i = 0; i < N; i++); trace ("code2 invoked"); } int1 = setInterval (code1, 10); int2 = setInterval (code2, 100);
Интересно, что функции оказываются в равноправных условиях, то есть теперь количество вызовов каждой из них примерно одинаково, и вызываются они по очереди.
Так происходит потому, что из-за изменения времени выполнения функций соблюсти интервалы становится невозможно (ни один, ни второй), в результате заявленные интервалы вообще перестают влиять на частоту вызовов.
А теперь проведем небольшое исследование setInterval на синхронность. Вопрос состоит в следующем: какой код может быть прерван, а какой - нет?
Создадим ролик из трех кадров, в первый кадр поместим такой код:
function code1 () { _global.v = 1; if (_global.v != 1) trace ("interrupted"); } function code2 () { _global.v = 2; if (_global.v != 2) trace ("interrupted"); } int1 = setInterval (code1, 10); int2 = setInterval (code2, 10);
Во второй - такой:
_global.v = 3; if (_global.v != 3) trace ("interrupted");
И в третий - такой:
gotoAndPlay (2);
В этом примере есть три "synchronized" -фрагмента, выделенные жирным шрифтом. Допустим, что Флэш может прерывать выполнение кода из одного обработчика setInterval для вызова другого, или же прерывать выполнение кода из кадра (второго кадра, в данном случае), с той же целью. Тогда рано или поздно наступит ситуация, когда один из трех фрагментов кода будет прерван другим, и на консоль будет выведено сообщение "interrupted!". Но на практике этого не происходит, из чего следует, что весь подобный код выполняется синхронно, и не может быть прерван.
А может ли обработчик setInterval быть вызван между вызовами кода из двух разных кадров? Это логично, иначе, когда еще ему вызываться. Но проверим это, переместив две строчки из второго кадра в третий.
Теперь второй кадр выглядит так:
_global.v = 3;
А третий - так:
if (_global.v != 3) trace ("interrupted"); gotoAndPlay (2);
И действительно, в консоль выводятся сообщения "interrupted".