Опубликован: 23.12.2005 | Уровень: специалист | Доступ: платный | ВУЗ: Московский физико-технический институт
Лекция 9:

Классы и клипы

Ограничения

Функцию watch нельзя использовать для мониторинга полей get / set.

Ни один из приемов, к сожалению, нельзя использовать для мониторинга "стандартных" полей типа _x, _y и пр.

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

Использование setInterval вместо линейки времени

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

Существует две функции setInterval , первая форма предназначена для вызова методов, которые не обращаются к this, то есть вызова как бы "просто функций", а другая - для вызова методов объектов:

  • setInterval (function, interval, params);
  • setInterval (object, methodName, interval, params);

Если пользоваться первой версией 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".

алексеи федорович
алексеи федорович
Беларусь, рогачёв
Тамара Ионова
Тамара Ионова
Россия, Нижний Новгород, НГПУ, 2009