Здравствуйте, гость ( Вход | Регистрация )

Свернуть

Новости

Форум Лучшее из галереи Уроки и статьи
07.12.2015 Выставочный зал: кошарик - персональная выставка
31.08.2015 Интересные ссылки для рисовальщиков
21.01.2015 Выставочный зал 2: Игрушки Олеси Гавриленко

27.12.2014 Выставочный зал: кошарик - персональная выставка
17.11.2014 Дуэль "Рыбки" - победитель Лисичка
05.11.2014 Конкурс иллюстраций "Снежная королева", до 31 января
30.10.2014 Дуэль "Рыбки" до 16 ноября
14.07.2014 Мастер-класс Мини-мишка в технике фелтинга
26.05.2013 Ау! Мы ищем таланты! – приглашаем модераторов!
Мilla
tn_gallery_9433_558_71984.jpg

06.01.2016 Виртуальный Музей: Русский живописец Василий Дмитриевич Поленов
28.12.2015 Виртуальный Музей: Нидерландский живописец Квентин Массейс
16.12.2015 Виртуальный Музей: Итальянский живописец Франче́ско Айец
17.11.2015 Виртуальный Музей: Луи Анкетен (Louis Anquetin)
11.11.2015 Виртуальный Музей: Русский живописец Алексей Иванович Корзухин
Файловый архив
06.09.2013 Прочее: Файлы к уроку "Чайная церемония"
05.09.2013 Журнал Art Tower: ArtTower Magazine #8
16.05.2013 Adobe Photoshop: Кисти: Reid Southen brush
16.05.2013 Adobe Photoshop: Кисти: Goro Fujita brush
16.05.2013 Adobe Photoshop: Кисти: Кисти для рисования в Photoshop
Блоги Новости в цифровом мире и мире дизайна
02.12.2014 Дама с каменьями: Вести с крыши 2
08.11.2014 Timenews: Вассерман: прежняя модель мировой экономики исчерпала себя
06.11.2014 Дама с каменьями: Приятные вести с крыши))) от Гаргула)
02.11.2014 Spell: Книги Дж. Кэмерон
22.10.2014 Vjaz: от ФУ до МА
25.11.2015 Комментарий от Foxx в Costa Rica Adventure Divers, Логотип для компании и рисунок на майку (maria_mer)
18.11.2015 Комментарий от maria_mer в Spellforce - майка, для фанов игры (maria_mer)
18.11.2015 Комментарий от maria_mer в Белая книга. Целитель - любительский прект (maria_mer)
09.04.2015 Комментарий от Romana в Книги Дж. Кэмерон (Spell)
08.04.2015 Комментарий от Romana в Я решил вернуться... (Элбирет)
16.03.2015 ФОТОФОРУМ-2015
01.01.2015 ARQUTE.com и ArtTalk.ru закрываются
19.01.2017 Конкурс дизайна логотипов
26.12.2016 ру/Ководство: О творческом развитии
14.10.2016 ру/Ководство: Разнообразие

 
Добавить ответ в эту темуОткрыть тему
> Основоположения программирования - часть V.1, События в AS2: основы
V
Des
сообщение 1.04.2009 - 16:52
Сообщение #1


тритониус
****

Звезда писателя I степениЗа вклад в развитие ArtTower.ru
Группа: Почетные граждане
Сообщений: 728
Регистрация: 9.12.2007
Из: Москва \ Питер
Пользователь №: 6553
дышу под водой
Галерея Блог


Симпатии:  68  


Предыдущая часть: Основоположения программирования - часть IV.3
Начало: Основоположения программирования - часть I

В этом уроке вы познакомитесь с одной из самых интересных частей программирования вообще и Action Script 2 в частности: с системой событий (events). Осваивать будем сразу "по-взрослому" - на объектах-"слушателях" (Listener-ах), потом уже переходя к принятому в AS2 упрощенному способу описания обработки событий.

Исходники к уроку

1. Что такое "событие"?

Для программы события - это а) возможность связи с "внешним миром", в т.ч. - возможность реагировать на действия пользователя (например, на движение мыши или нажатия клавиш на клавиатуре) и б) возможность т.н. асинхронной работы - т.е. такой организации программы, когда что-то происходит не просто последовательно, шаг за шагом, и только в одном модуле или с одним объектом, но в зависимости от непоследовательных или "внешних" по отношению к программе изменений - например, после окончания загрузки файла-картинки или после установления соединения с сервером.
Action Script умеет реагировать на множество внешних событий - движение мыши, нажатие и отпускание клавиши1 мыши, начало, прохождение курсора мыши над роликом и выход курсора за пределы того или иного ролика (MovieClip-а), процесс и окончание загрузки внешнего файла, события, помогающие отслеживать и управлять соединением при обработке потокового звука и видео, и некоторые другие.
Система событий может показаться несколько запутанной и сложной, но, разобравшись, вы будете легко реализовывать любые логики работы программы.
Несколько забегая вперед, приведу пример использования событий с загрузкой изображений. На примере вам будет проще понять сущность происходящего, когда, извиняюсь за каламбур, флэш-программа реагирует на происходящее.
Итак, пример.
Задача: загрузка и показ Изображения из внешнего файла. Причем загруженное Изображение нужно отмасштабировать.
В самой загрузке Изображения ничего сложного нет. В любой MovieClip можно загрузить внешний файл - для этого существует класс MovieClipLoader, который позволяет не только загружать внешние swf-, JPEG- и GIF-файлы, но и отслеживать начало загрузки, ее ход и окончание. А нам именно это и понадобится для решения одной не совсем поначалу очевидной проблемы.
Предположим, что мы написали код, который обеспечивает создание нового ролика и загружающий в него нашу картинку:

CODE

var mc:MovieClip = _root.createEmptyMovieClip("mc",_root.getNextHighestDepth());
var ldr:MovieClipLoader = new MovieClipLoader();
ldr.loadClip("./images/image.jpg",_root.mc);


Однако если теперь мы напишем что-то вроде

CODE

_root.mc._width /= 2;
_root.mc._height /= 2;
_root.mc._x += 150;
_root.mc._y += 150;
_root.mc._rotation -=45;


то... ничего не увидим. Т.е. даже хуже: иногда мы можем увидеть результат. Иногда - нет. Иногда "сработают" положение на сцене (_x,_y и _rotation), но не _width и _height. Все зависит... от скорости соединения у клиента, от размера (неизвестного нам) image.jpg, ..., ...
Почему?
Потому что, если разобраться, то наша программа, еще только начав загружать изображение, уже пытается использовать в вычислениях свойство _width загружаемого изображения. Но если с момента, когда началась загрузка (loadMovie) до момента, когда программа пересчитывает ширину и высоту изображения, это Изображение еще не загружено, то и свойства _width и _height ролика mc еще пока равны 0. Ведь ширина и высота загружаемого, но еще недогруженного Изображения еще недоступны! - вот программа честно и выведет наш ролик в размере 0 x 0 пикселов...
Т.е. нам нужно дождаться окончания загрузки, чтобы можно было использовать эти свойства. Но ведь... мы не знаем (программа не знает), сколько ждать. Мы ведь заранее не знаем, какая именно картинка заказчивается - какого размера, и тем более не знаем, быстрый ли интернет у посетителя.
Вот тут нас и выручают события.

Работает это так:
- создаем объект-"слушатель" (Listener)
- ставим ему задачу отслеживать ("слушать") событие "окончание загрузки" (onLoadInit) и задаем функцию-обработчик, которая будет выполняться при наступлении этого события
- добавляем объект-слушатель к переменной класса MovieClipLoader - подписываем загрузчик на данное событие
...и после этого уже стартуем загрузку.
Вот так:
CODE

var mc:MovieClip = _root.createEmptyMovieClip("mc",_root.getNextHighestDepth());
var ldr:MovieClipLoader = new MovieClipLoader();
var listener:Object = new Object();
listener.onLoadInit = function (target:MovieClip) {
target._width /= 2;
target._height /= 2;
target._x += 150;
target._y += 150;
target._rotation -= 45;
}
ldr.addListener(listener);
ldr.loadClip("./images/image.jpg",_root.mc);
}

Теперь наши вычисления будут выполнены только при наступлении события "onLoadInit", т.е. когда весь внешний файл загружен и все его свойства становятся доступны. И теперь - все в порядке.

В нашем примере "onLoadInit" - это событие (event), на которое подписывается ролик mc, а функция, которая вызывается при наступлении этого события - обработчик события (event handler). И событие передает этой функции в качестве аргумента ссылку на тот самый MovieClip, который событие вызвал - target.

Не так уж сложно? - пожалуй, да. Пока у нас одно событие...
Даже попытавшись организовать "по всем правилам" (т.е. без глюков и багов) загрузку простой серии изображений, мы уже столкнемся с неожиданными сложностями. Как отследить загрузку сразу нескольких клипов\изображений, что будет, если загрузить мы попытались, а файла по ссылке нет или коннект оборвался - эти и другие интересные сложности будут в следующей части урока, а пока мы вернемся к событиям, которые позволят нам, наконец, сделать активные кнопки и заставить нашу флэшку реагировать на мышь.

2. Основные мышиные события, или Mouse Events.

Подумаешь, кнопку сделать... нажали - поехали. Отпустили - поехали... Простое дело, да?
А как вы думаете, сколько "мышиных событий" может обрабатывать AS2? 2? 4? 8? Маловато будет... 11!
Вот они:

("mc" = MovieClip; Mouse = стандартный класс, описывающий "поведение" мыши - события мыши, которые не относятся к конкретному объекту, некоторые методы и свойства объекта "Mouse")

mc.onRollOver
mc.onRollOut
mc.onDragOver
mc.onDragOut
mc.onPress
mc.onRelease
mc.onReleaseOutside
mc.onMouseDown
mc.onMouseMove
mc.onMouseUp

Mouse.onMouseWheel

Почему так много? Да потому что в Flash все (или... почти все), включая все реакции на мышь, описываем мы сами. Все "мелочи", которые, работая в Windows или просматривая веб-сайт, мы и не замечаем чаще всего - тут надо подробнейшим образом описать: что происходит, когда мышиный курсор заходит на тот или иной MovieClip, что происходит, когда курсор уходит за пределы этого ролика, что происходит, когда пользователь нажал кнопку мыши, что - когда он повернул колесико прокрутки, что - когда ему вздумалось нажать кнопку над роликом, переместить мышь с нажатой кнопкой и отпустить за пределами ролика...
Конечно, описывать нужно только то, что нам непосредственно нужно по логике и замыслу флэш-программы. Если нам колесо мыши неинтересно - мы его и не описываем, а программа никак на него и не реагирует2...

В общем, реакция на события мыши описывается так же, как любое событие. Например, предположим, что у нас уже есть на сцене ролик с именем экземпляра btn_mc и мы хотим, чтобы он реагировал на прохождение курсора мыши над ним. В ролике два кадра, в первом из них пишем stop();
В первом кадре основного таймлайна пишем так:

CODE
btn_mc.onRollOver = function() { this.gotoAndStop(2); }
btn_mc.onRollOut = function() { this.gotoAndStop(1); }


Вроде, работает... Однако - попробуем нажать мышь над нашей "кнопкой", а отпустить - за ее пределами. Оп-па! А кнопка-то осталась "зеленой" - т.е. событие onRollOut не "отработало"!
Вот для этого случая и существуют события onReleaseOutside (отпускание левой кнопки за пределами), onDragOut ("вытаскивание" за пределы ролика)

Дописываем:

CODE
btn_mc.onReleaseOutside = function() { this.gotoAndStop(1); }


(ключевое слово this обозначает тот объект, для которого определена функция или метод (дословно - "этот"). Заодно сразу: выражение _parent означает "родителя" того объекта, для которого определена функция или метод.
Напр., если у нас есть клип mc, в нем - клип inner_mc (т.е. полное имя второго из них будет _root.mc.inner_mc), то код

mc.inner_mc.onRelease = function () { this._parent.gotoAndStop(5); }
будет останавливать ролик mc на 5-м фрейме каждый раз, когда отпускается клавиша мыши на ролике inner_mc, а код
mc.inner_mc.onRelease = function () { this._parent._parent.gotoAndStop(1); } - останавливать в этом же случае на первом кадре основной ("рутовый") ролик.

Опишу остальные основные события мыши:
onDragOver - когда пользователь проводит курсор мыши над роликом с уже нажатой кнопкой
onPress - момент нажатия левой кнопки мыши на ролике
onRelease - момент отпускания левой кнопки мыши над роликом

onMouseDown - момент нажатия левой кнопки мыши. Обратите внимание: это событие не отслеживает, над роликом ли нажата кнопка или вне его.
onMouseUp - момент отпускания левой кнопки мыши. Не отслеживает, над роликом ли отпущена кнопка.

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

CODE
var mListener:Object = new Object();

mListener.onMouseWheel = function (delta:Number) {
_root.btn_mc._rotation += 5*delta;
}
Mouse.addListener(mListener);


3. Особенности синтаксиса обработки событий в AS2

Надо сказать, что описание событий в AS2 - это то, в чем эта версия языка сильно уступает AS3. Стремясь упростить описание часто повторяющихся и простых действий вроде нажатия кнопок мыши для новичков в программировании, Macromedia наворотила весьма запутанную систему записи и логику обработки событий. Из AS3 все это упрощенческое безобразие выброшено и там, "прорвавшись" раз через сложности добавления обработчиков событий в зависимости от их типа и логики их обработки, можно стройно и логично описывать целые каскады событий и\или отделять основную логику программы от "обслуживающих" функций. В AS2 же приходится мириться с тем, что обычное описание события - т.е. "подписывание" объекта на то или иное событие и передача в аргументе (свойстве) события указания на объект, его вызвавший, и некоторую другую информацию, в некоторых случаях невозможно, а простота в простых случаях оборачивается пустыми сложностями в мал-мал нетривиальных.
Впрочем, для начинающего написать btn_mc.onRelease = function() {...} (AS2) проще, чем btn_mc.addEventListener(MouseEvent.MOUSE_UP,onMouseUpHandler); (AS3)... А на то, что вы можете пока и не понять, почему и насколько это хуже - пока закроем глаза. В следующей части, надеюсь, это понимание придет.

Очевидно, исключительно для удобства начинающих в AS2, помимо полного описания реакции на события (с объектом-слушателем (Listener), который "подписан" на события определенного типа (events) и вызывает соответствующий обработчик события (event handler)), существует еще как минимум два способа "присоединить" обработчик события к определенному объекту-мувиклипу:
1) описать функцию как свойство MovieClip-а. Так, например, можно описать события кнопки (Button) или ролика (MovieClip) onRelease, onReleaseOutside, onPress, onRollOver, onRollOut, onDragOver, onDragOut.
Чтобы не ограничиваться "мышиными" событиями, приведу в пример также событие onLoad, которое вызывается при окончании загрузки XML и LoadVars.
Синтаксис такого описания события:

CODE
mc.onEvent = function(){ <...> код обработчика события <...> }


2) Можно написать скрипт не в кадре таймлайна, а в скрипте, "прикрепленном" к объекту. В этом случае в таком скрипте пишется сразу функция-обработчик с указанием типа события, а "слушателем" будет являться тот объект, к которому "прикреплен" скрипт. Синтаксис такого скрипта:

CODE
onClipEvent (event) { <...> код обработчика события <...> }
/*
event - это load (окончание загрузки), unload (выгрузка клипа),
mouseMove, mouseUp, mouseDown, enterFrame (вызывается на каждом проигрываемом фрейме),
keyDown, keyUp (соответственно нажатие и отпускание клавиши на клавиатуре)
*/


Я категорически не советую пользоваться этой сокращенной записью. Как и во всех случаях, когда код AS "разбросан" по ролику и куски его находятся где-либо, кроме главного таймлайна, программа становится абсолютно нечитаемой и трудноотлаживаемой. Что - гораздо более серьезный "минус", чем может показаться на первый взгляд, если вы, конечно, собираетесь хоть в какой-то степени накапливать код многоразового назначения (что следует делать всегда, дабы не изобретать уже изобретенный вами же велосипед через месяц-другой...)
И тем не менее, описать эту запись я просто обязан - как мин., чтобы вы знали, что может скрываться в недрах какой-нибудь кнопули 15-го уровня вложенности в чужом, тщательно разбираемом вами в учебных целях, коде.

Пример:
CODE

onClipEvent (keyDown) {
if (Key.getCode() == Key.RIGHT) {
this._parent.nextFrame();
} else if (Key.getCode() == Key.LEFT) {
this._parent.prevFrame();
}
}




этот фрагмент кода реагирует на нажатие клавиши на клавиатуре, и если нажатая клавиша - одна из стрелок LEFT или RIGHT - то соответственно проигрывает предыдущий или следующий фрейм ролика-"родителя".

Продолжение
____________________________________

1 AS2 реагирует только на нажатие и отпускание левой клавиши мыши. Правая клавиша зарезервирована для вывода системного контекстого меню, которое в минимальном варианте, при запрете на вывод дополнительных функций, выводит контекстное меню с двумя пунктами - "About" (со ссылкой на сайт Adobe) и "Settings" ("Настройки"; позволяет настроить опции флэш-плагина)
2 Вот как раз с колесиком-то это не совсем так: если мы не отключили у текстового поля свойство mouseWheelEnabled - то текст в динамическом текстовом поле, больший по размеру, чем помещается в это поле, будет прокручиваться колесиком мыши без всяких усилий с нашей стороны... Пользы от чего, впрочем, мало, поскольку прокрутку текста почти всегда организуют "вручную", прописывая опять-таки все происходящее в коде.
____________________________________


Автором урока является Des.
Запрещается копирование и публикация урока на других сайтах без письменного согласия автора и размещения ссылок.


The tutorial is written by Des.
No part of this tutorial can be copied/pasted on any other website without the author's express written permission.


Сообщение отредактировал Des - 3.05.2009 - 10:57


--------------------
"Высшая мудрость - умение разговаривать с людьми" ((с) Ямамото Цунэтомо (Дзётё), "Хагакурэ")
Вернуться в начало страницы
 
+Ответить с цитированием данного сообщения

Быстрый ответДобавить ответ в эту темуОткрыть тему
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



- Текстовая версия форума Сейчас: 20.10.2017 - 20:45