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

Клипы и ролики. Специальные возможности языка

Реакция на события

Обсуждая ранее тему реакции на события, мы подробно говорили лишь о несколько устаревших способах это делать. Ведь к тому времени мы с вами еще не знали о том, что представляют собой объекты в ActionScript и как во Флэше определяются функции. Теперь мы можем изучить более удобный способ работы с событиями - переопределение в объектах ( клипах ) функций класса MovieClip (объектом которого каждый клип является, если только этого нарочно не испортить). Итак, для работы с событиями класс MovieClip имеет следующие методы, подлежащие переопределению:

  • onData - в клип загружали данные (см. главу 14) и пришла очередная порция.
  • onDragOver - мышь в нажатом состоянии протащили через границу нашего клипа внутрь (после того, как мышь в нажатом состоянии была вытащена наружу - см. пояснения в главе 1).
  • onEnterFrame - начинается процесс переключения кадров.
  • onKeyDown - нажата клавиша на клавиатуре. Узнать, какая именно клавиша была нажата, можно при помощи статических функций класса Key, а именно, вызвав Key.getAscii() или Key.getCode() для получения символа или его ASCII-кода соответственно. Чтобы этот механизм работал, добавьте после определения функций реакции на мышь следующий код: Key.addListener(clip) ; (предполагаем, что clip - это тот клип, в котором вы определяете функции реакции на события клавиатуры; не забудьте, что события клавиатуры будут приходить только если на флэш-плеере будет фокус ввода).
  • onKeyUp - отпущена клавиша на клавиатуре (последняя отпущенная клавиша определяется так же, как и в предыдущем случае).
  • onKillFocus - фокус ввода ушел с клипа. В функцию реакции на это событие передается один аргумент: ссылка на тот объект, к которому перешел фокус.
  • onLoad - клип только что загрузился (например, сейчас мы переключились на кадр, в котором этот клип впервые появляется).
  • onMouseDown - кнопка мыши нажата в произвольной точке ролика, не обязательно на клипе.
  • onMouseMove - мышь передвинута (в произвольной точке ролика, не обязательно на клипе ).
  • onMouseUp - кнопка мыши отпущена.
  • onPress - кнопка мыши нажата на клипе.
  • onRelease - кнопка мыши нажата на клипе и на нем же отпущена
  • onReleaseOutside - кнопка мыши нажата на клипе, а отпущена снаружи.
  • onRollOut - мышь выехала с территории клипа в ненажатом состоянии.
  • onRollOver - мышь зашла на территорию клипа в ненажатом состоянии.
  • onSetFocus - фокус ввода с клавиатуры поставлен на данный клип. В функцию реакции на это событие передается один аргумент: ссылка на объект, с которого перешел фокус.
  • onUnload - клип выгружается (только что мы ушли с последнего кадра, где данный экземпляр существовал).

Не забудьте, что при реакции на события от мыши координаты мыши (относительно произвольного клипа ) вы можете определить, опросив свойства клипа _xmouse и _ymouse. Вот пример определения функций реакции на события от мыши и клавиатуры:

// Определяем реакцию на события от клавиатуры
clip.onKeyDown = function(){
   trace("KeyDown: " + Key.getCode());
}
clip.onKeyUp = function(){
   trace("KeyUp: " + Key.getCode());
}
// Подписываем данный клип на получение этих событий
Key.addListener(clip);
// Определяем реакцию на события мыши
clip.onMouseDown = function(){
   trace("MouseDown: x = " + _xmouse + " y = " + _ymouse);
}

Запустив пример, вы сможете убедиться, что при реакции на события клавиатуры работает автоповтор. Не забывайте только, что фокус ввода должен находиться на окне с проигрываемым роликом.

Обратите внимание, что писать Mouse.addListener(clip) не нужно: любой клип считается по умолчанию подписанным на события мыши.

Подписка на события

В этом параграфе мы, кроме термина " событие ", будем использовать и термин "сообщение". В нашем контексте это будут синонимы, хотя и с немного различными оттенками смысла: происходят события, посылаются по этому поводу сообщения (хотя иногда мы будем писать, что посылаются события ), принимаются опять-таки сообщения, но подписка производится на события. Итак, как подписаться на события Флэш? Во-первых, для этого надо знать, какой объект рассылает связанные с данным типом событий сообщения. Мы будем называть такой объект публикатором. Предположим, что имя у этого объекта broadcaster1 и транслирует он всем желающим событие event1. Тогда подписать объект myObject на это событие мы сможем так. Пишем: broadcaster1.addListener(myObject) ; после этого у объекта myObject будет вызываться метод myObject .event1() всякий раз, когда происходит событие event1. В предыдущем подпараграфе мы видели, как происходит подписка на события onKeyUp и onKeyDown. Правда, в этом случае мы заранее знали, что объект Key (это именно объект, хотя и определяющий собой класс; подробнее о том, что представляют собой такие объекты, вы узнаете в главах об объектах и наследовании) рассылает соответствующие события. И что об этом заботится инфраструктура Флэш. А нельзя ли нам самим разослать какое-нибудь событие? Оказывается можно, и для этого существует недокументированный системный объект ASBroadcaster. Работа у этого объекта такая: он формирует публикаторы сообщений. Происходит это следующим образом: пишем ASBroadcaster.initialize(broadcaster1) ; и после этой операции у объекта broadcaster1 появляется метод broadcastMessage, которому в качестве аргумента нужно передать строчку с именем события. Затем мы вызываем этот метод, когда хотим отправить событие.

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

// Создаем объект, который будет работать
// публикатором сообщений
_global.myBroadcaster = new Object();
// Делаем этот объект публикатором
ASBroadcaster.initialize(myBroadcaster);
// Создаем объект, который будет посылать свое сообщение
// через только что созданный публикатор
sender = new Object();
sender.sendCustomEvent = function(){
   myBroadcaster.broadcastMessage("onCustomEvent");
}
// Создаем два объекта, способных реагировать на сообщение
// по имени onCustomEvent
// Первый объект
receiver1 = new Object();
receiver1.onCustomEvent = function(){
   trace("CustomEvent получен объектом receiver1");
}
// Второй объект
receiver2 = new Object();
receiver2.onCustomEvent = function(){
   trace("CustomEvent получен объектом receiver2");
}
// Подписываем на сообытия, рассылаемые через
// myBroadcaster объект receiver1
myBroadcaster.addListener(receiver1);
trace("----- Посылаем сообщение первый раз -----");
sender.sendCustomEvent();
// Теперь подписываем на события от myBroadcaster
// еще и объект receiver2
myBroadcaster.addListener(receiver2);
trace("----- Посылаем сообщение второй раз -----");
sender.sendCustomEvent();

После запуска этого кода получаем в консоли:

----- Посылаем сообщение первый раз -----
CustomEvent получен объектом receiver1
----- Посылаем сообщение второй раз -----
CustomEvent получен объектом receiver1
CustomEvent получен объектом receiver2

Видим, что второй объект начал реагировать на событие только после того, как его подписали на получение сообщений от соответствующего публикатора.

Если хотите, можете посмотреть, как устроен ASBroadcaster внутри, вот по этой ссылке: http://www.flash-ripper.com/articles/flash/2002_05_22_asbroadcaster.htm#notes

(Или, если вы предпочитаете англоязычный оригинал статьи, читайте его здесь: http://www.flashguru.co.uk/000032.php, правда, в нем есть незначительные опечатки, исправленные при переводе).

Впрочем, устройство ASBroadcaster довольно очевидно, и вы сами легко такой напишете - сейчас или после несколько более тесного знакомства с ActionScript. В самом деле, при подписывании объектов нужно всего лишь добавлять в массив подписываемые объекты; а при посылке сообщений - вызывать у этих объектов функцию с именем, совпадающим с именем события.

Итак, вы теперь знаете, как рассылать произвольные события произвольным объектам. Является ли событийная модель Флэш МХ оптимальной? Могут быть разные мнения на этот счет. Из ее недостатков можно указать следующие: во-первых, со встроенными событиями Флэш МХ не передается никакая информация (приходится "забирать" ее из определенного заранее глобального места, а это не соответствует объектной парадигме). Затем, чтобы подписаться на сообщение, надо знать имя публикатора этого сообщения. Конечно, можно стандартизировать в вашем проекте эти имена; но в любом случае, публикатор надо еще и заводить. Если же вы заведете один общий публикатор для различных событий, вы можете столкнуться с тем, что механизм подписки-отписки не оптимизирован для такого случая (хотя вы, скорее всего, не обнаружите замедления работы программы). Есть еще и другие причины завести свои события , например, добавление возможности выводить посылаемые сообщения в лог, "ручная" проверка типа данных, передаваемых с сообщением, и т.п. Короче говоря, если вы точно знаете, зачем вам это надо, - заводите свои события ; во всех остальных случаях, разумеется, лучше пользоваться встроенными событиями Флэш МХ. Также не возбраняется, конечно, и сочетать свои события и встроенные: первые, скажем, можно выводить в лог (в отладочном режиме) и передавать с ними информацию, а вторые, не загромождая собой лог, будут, предположительно, работать несколько быстрее ваших.

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