Рубрикатор

Все материалы, относящиеся к программе и технологии Macromedia Shockwave Flash

(материалы даны в хронологической последовательности, как они присылались автором)


Вторая часть рубрики "Записки флэшера". Первая часть здесь.


из номера за 6 мая 2000

(прим. редактора: для полного понимания статьи необходимо скачать учебный ролик (.fla, 18kb)).

 

Flash 4 logoНемного практики.

Хочу сменить свой менторский тон на ещё более менторский - хочу рассказать как надо делать и как не надо.
Что может нового, неизведанного HTML'ём внести Flash в web-страницу? Анимацию? Да (о DHTML пока позабудем). Интерактивность? Да (ремарка та же). Если серьезно подумать - огромное количество анимаци может пойти лишь во вред сайту (скажу вам, как сделавший сам большое количество таких сайтов). Но это уже вопрос культуры, тут я судить могу лишь отчасти (но могу). С интерактивностью тоже лучше не переборщить - когда простое нажатие на кнопку, имеющее своей целью просто открыть некое меню, сопровождается сложным букетом событий (я не говорю о тех событиях, которые поддерживают mood сайта, а о тех, у которых это получается плохо) - это непорядок. Притягивать за уши эффекты не надо - если ты по настоящему крут, умей отказать себе в попытках доказать свою крутизну другим (не за свой, ессно, счет :)).

Опасайтесь эффектных, но избитых приемов только ради них самих - если претендуете на профессионализм, конечно. Вот, такие вилы в бок.

Теперь - о самих приемах. Рассмотрю несколько простых задач, встречающихся часто, но раскрывающие суть работы (по крайней мере, моей работы). Мы сделаем три элемента управления - кнопку, простое меню и слайдер.

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

Что пользователь ждет от кнопки? С такого вопроса надо начинать любую разработку. Пока загружается среда разработки и создается новый документ надо подумать. Пользователь должен иметь представление о том, что он нажимает еще ДО акции нажатия. Хорошо. Пользователь должен знать о том, что это кнопка. И третье - что такое кнопка в повседневной жизни. С этого и начнем - с планирования. Кнопка по жизни - обычно круглый или прямоугольный объект, нажимаемый пальцем, тем или иным способом, предназначенный для этой роли. Кнопка на экране может иметь несколько более абстрактный вид или совершенно распределенный все от общего устройства предметной среды экрана. Могут менять своё состояние от нажатия, могут НЕ менять его и могут, изменив состояние, вернуться в исходное. Решаем, какую кнопку мы делаем. Мы делаем кнопку, возвращающуюся в своё состояние, но не сразу, а спустя какое-то время, несколько инерционно. У нас есть дизайн, на его основе сделаем требующуюся нам кнопку. Решаем идеологически - что это будет. Использовать простую кнопку с состояниями Up/Over/Down нельзя - мы не получим инерционности, да и наше движение может не завершиться, когда мы отожмём мышь с кнопки, кроме того - проблема возвратного движения - где оно может начинаться? Из состояния Down возвращаемся в Up или Over, но там у нас другая анимация, а вернее - ее отсутствие. Этот подход нас не устраивает.

Путь, которым мы пойдем следующий - надо построить поток (clip) 3го типа - то есть реагирующий на действия извне. Это уже другое дело - мы сами будем решать, как и когда производить "нажатие" и "отжатие" кнопки. Строим этот поток : последовательность анимации нажатия - пауза (кадры без анимации) - последовательность анимации отпускания кнопки.

В этом потоке весь наш дизайн. Управлять мы будем фиктивной кнопкой (я честно признаюсь, последнее время почти не работаю с кнопками другого вида, но ПОЧТИ. Иногда все же использую - случаи разные бывают). Как ее создать, я рассказывал выше.

С чего начинается наша анимация? каждый объект в сцене КАК-ТО появляется. Он закрепляется в сцене и сосуществует там вместе с другими элементами - это очевидно. Взаимодействует каким-то образом с другими потоками и т. д. Включать ли эту "входную" анимацию в сам поток или произвести с нам водные действия - вопрос уже зависящий от задачи - от того, как часто этот объект будет использоваться, будет ли ему необходима каждый раз однотипная анимация появления или уникальная и всё в таком духе - это уже планируйте сами. В примере я поступил тем путем, что построил объект, не знающий как себя ввести в сцену, а вся работа по этому поводу переложена на материнский поток, оформленный как поток 2-го типа - единоразово выполняющийся - реализующий наш простой сценарий. После чего все действия в сцене останавливаются и появляется наша фиктивная кнопка (с её появлением хлопот нет, надеюсь). Что происходит теперь? Наш объект-кнопка (не путайте с реальной flash-овой фиктивной кнопкой) - который является clip'ом стоит и ждёт реакции пользователя. Устроен он так, что в любой момент только толкни его командй Play - и он "нажмется". Но в самом первом кадре у него команда Stop, которая заставила его застыть в бездействии. / На самом деле, это не обязательно - можно организовать (другой) поток так, чтобы в нем происходило принудительно-зацикленное действие, но командами извне он переходил бы из одного состояния в другое, вариаций может быть полно, всё зависит от задачи. / Этот самй Play для этого потока (через трансляцию TellTarget) и происходит с потоком при нажатии на нашу фиктивную кнопку (что выглядит для пользователя как "нажатие" на нашу кнопку-объект).

Кроме того, мы указываем посредством установения переменной-флага released состояние того, отпущена ли кнопка (естественно, устанавливаем его в False). Что происходит в самом объекте? в нём происходит анимация "залипания" кнопки, по выполнении которой в ключевом кадре слоя, содержащего управляющие коды проверяется услови на это самый флаг released. В случае, если он отрицателен (False) поток останавливается (кнопка "ужалась" и её не отпустили).

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

Осталось только выяснить, как мы можем "отжать" нашу кнопку. Естественно, что надо для фиктивной кнопки прописать обработчик события OnRelease. Он как раз и переназначит наш флаг released на положительное значение, что просигнализирует кнопке о том, что ее "отжали". Но так как наш поток в этот момент может уже стоять, а акции в кадре уже выполнились и ничто уже не переменит сурового решения Stop нам нужно будет всеголишь толкнуть наш поток далее - к паузе-отжиманию-исх. состоянию. Для этого снова посредством трансляции комманд TellTarget меняем значение release на True, это нас застрахует от того, что поток остановится при проверке условия на отжатие ещё в процессе анимационной последовательности "залипания", после чего также командуем Play. Здесь мы убиваем двух зайцев двойным выстрелом, причём какого когда - неизвестно :).

Хочу дать группу пояснений по поводу проекта. Первое касается того, что кроме события OnRelease тот же обработчик отрабатывает и OnDragOut - для чего? Чтобы не случилось, что вы сползете курсором с кнопки, а она останется залипшей.
Еще комментарии по поводу TellTarget. Я рекомендую рассматривать эту команду как вызов куска кода внутри потока. тогда конструкция с переменной released сразу станет понятной. К сожалению, не с самого начала очевидно, что все происходит именно так - что пространство имен переменных по TellTarget и за его пределами различны - документация или умалчивает об этом, или отделывается крайне скупой информацией. О нотации переменных я хотел бы рассказать в дальнейшем.
Прочту ещё пару нотаций о нотациях :) - крайне рекомендую называть символы своими именами (как и слои!),

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

Kunck (e-mail)

 

скачать заготовку ролика в формате FLA можно здесь (18kb). Готовый (SWF) - здесь (2.5kb).

 


из номера за 11 августа 2000

 

Flash 4 logo"Разберёмся с ещё одной общеупотребительной задачей - построим слайдер. Вопрос построения меню я хочу опустить, поскольку всё сказанное ниже может относиться и к вопросу построения меню как элемента управления.

Вспомним хорошенико, что же такое слайдер. Обычно - это вертикальная/горизонтальная полоска с бегунком и с кнопочками, сидящими на краях этой полоски. Отлично, получив дизайн, кидаемся в прорубь создавания нашего слайдера. Однако, взглянем на дизайн ещё раз. Страшно стало? Ещё и не такое придумать могут, будьте уверены. Назначение этой контрукции (слайдера в его тривиальной сущности) - выбрать спектральную компоненту, причём поступило желание, чтобы при передвижении бегунок менял окраску на цвет, дополнительный к тому, который отображается в окошке. Кроме всего прочего замечательна идея о том, что "капли краски" по краям этой радужной ленты - те самые кнопки, которые пербрасывают грубо бегунок к ближайшему чистому спектральному цвету (красная - в сторону уменьшения - фиолетовая в сторону увеличения числа H). Последнее желание - отображать на бегунке текущее значение любимым шрифтом дизайнера. Ах, да, ещё: как насчёт управления с клавиатуры?

Давайте решим для себя раз и навсегда - если мы делаем какую-то СЛОЖНУЮ задачу, то сделаем её так, что сможем в других проектах решать аналогичные задачи, используя эти наработки с минимальными модификациями (касающихся в основном дизайна). Это потребует от нас определённой концентрации и некой внутренней дисциплины. Вот несколько правил, которыми я буду руководствоваться, создавая элемент управления, с замашкой на универсальность:

1. все названия символов будут начинаться со слова Hslider - нет ни малейшего желания разбираться в будущем в своём проекте заново и думать, какие могут у меня быть конфликты имён. Кроме этого - поместим их в одну папку, тоже Hslider.

2. я НЕ МОГУ знать, какие и как я буду строить интерактивные среды в будущем - но я могу построить элемент, которому будет наплевать на то, что происходит вовне его. Эта идея ценна тем, что из неё автоматически следует необходимость определения элемента управления как ОТДЕЛЬНОГО объекта, имеющего какой-то интерфейс общения с внешним миром. Угадайте, чо это будет по сути своей?

Интерфейс определяем следующим образом:

1. Что мы должны знать от объекта - список данных, которые мы можем немедленно затребовать из объекта - проще говоря - список переменных, выходных параметров объекта. В нашем случае - это параметр H - цветность, ради получения которой мы и затеяли эту пьянку. Как следствие - держим этот параметр на самом верхнем уровне в объекте.

2. Мы можем варьировать рабочие свойства объекта - в нашем случае, к примеру - количество грубых градаций на шкале цветности (gradations). Опять же, для доступности и закрытости внутреннего устройства определяем эти данные на верхнем уровне объекта.

3. Конечно, мы можем хотеть от объекта чтобы он выполнял действия того или иного плана по команде извне - что вполне очевидно - (допустим: "выставлены параметры - перевести объект в состояние, соответствующее этим параметрам"). Каким путём пойти здесь? Есть как минимум 3 методики: 1. премещаться по потоку управлением извне в те точки объектного потока, которые удовлетворяют нашим условиям. минусы - пренебрежение объектной идеологией, необходимость анализа объекта извне. плюсы - бывает, что не все действия можно или нужно выполнить сразу, в рамках этого же фрейма. 2. Можно повесить в объекте следящий поток, выполняющий те или иные действия при изменении параметров. минусы - создавая объект мы перходим в другое пространство имён и иногда крайне неуклюже выглядит код, который в принципе мог бы выполняться и в главном потоке. плюсы - контроль сосредоточен в одном месте. 3. не скрою, что это мой любимый путь - использовать вызовы CALL. плюсы - действия распределены и сгруппированы. пространство имён - верхний уровень объекта. Минусы - есть вероятность перекрёстных вызовов, что достаточно трудно отлавливается. зачастую большая вложенность вызовов порождает слишком большое число действий, которое flash переварить не в состоянии. Все действия выполняются немеленно, что нужно не всегда.

4. Сам объект может иногда сообщать о том, что с ним случились какие-то преобразования (в нашем примере - допустим "нажата кнопка бегунка - першел в состояние выбора данных, выходные параметры могут меняться") Рекомендации - те же, только в данном случае управляемым оказывается поток, объемлющий объект. Не поленюсь ещё раз сказать о том, что мне в этом случае всё равно ближе идея с вызовами CALL и установкой определённых параметров в объемлющем потоке.

все эти умствования приводят нас к следующим выводам.

интерфейc:
входящие gradations (default= 7)
выходящие H
внутренние вызовы (методы) INIT(gradations);
внешние вызовы (события) HSLIDER_DRAG_START(hslider_name);
HSLIDER_DRAG_STOP(hslider_name);

Читая меня на протяжении столь длительного времени нельзя не заметить, что я стараюсь дать побольше материала, касающегося идей работы во Flash, отвлечённо от той или иной темы - рекомендации мои универсальны, хотя метода не идеальная, и, тем более, не единственно верная. Но она такая, и в дальнейшем изложении я всё равно буду придерживаться тех направляющих, которые обозначил много ранее - потоково-объектно-событийных определений. Хочу отметить, что полемику по этому вопросу я только приветствую, что случается редко :).

После такой лирики и момента самолюбования всё же вернёмся к тому, чем мы занимаемся изначально - созданию слайдера. Что мы уже сделали, не шевельнув ни разу мышкой в сторону Flash-среды? мы точно знаем, как наш слайдер должен выглядеть со всех точек зрения - на экране и в программном коде. прекрасно. Набираем побольше воздуха в лёгкие и запускаем Flash.

Вспоминаем правило 1. Применяем его. После этого создаём САМ слайдер. Имя ему - Hslider_ - почему - надеюсь догадаться несложно.

В принципе, нам не ставили задачу специальным образом разработать введение слайдера в сцену, поэтому мы не разрабатываем никакой intro-анимации а сразу блокируем поток в первом фрейме, где у нас так же находится вся графика. Вспомним, что по требованиям интерфейса мы должны создать фрейм с меткой INIT, в котором разместим инициализационный код. И в принципе, по устройству самого обекта всё. Одно только замечание - лучше всего, когда элемент помещённый в "среду" сразу начинает функционировать - для этого и существует инициализирующий код в первом фрейме. Практически - это установка праметров по умолчанию и вызов INIT дя их трактовки. Очень важное следствие из этого - проводите принудительную инициализацию объекта, если она вам потребуется, с задержкой на 1-2 такта от его появления в сцене - это снимет вопросы о "инициализационных" коллизиях достаточно малой ценой.

Kunck (e-mail)


 Пишите! Мне интересно будет Ваше мнение, замечания и пожелания. Указывайте в письме НЕсогласие на опубликование. Если ничего не будет указано - публикую по своему усмотрению. Если письмо не личное, конечно...

Журнал поддерживается ISP Деловая Сеть Иркутск