Предмет: Flash-технологии, программы, редакторы, классы, библиотеки. Методика: Изучение шаг за шагом, поиск новых решений, сбор ссылок, новостей и мнений, разбор примеров. Цель: Сбор, обработка и накопление тематической информации.
среда, октября 14, 2009
Новый подблог "Flash-разработка. Сотрудничество"
вторник, октября 13, 2009
Спасительный cacheAsBitmap и wmode=transparent
this._infoContainer.cacheAsBitmap=true; (_infoContainer - это окошко, контейнер для плашки и указателя, DisplayObjectContainer). Теперь всё выводится корректно.понедельник, октября 05, 2009
Копипаст фильтров из CS во Flex
- В тестовом файле создаем клип образца, визуально похожего на то что у нас должно быть во flex - например, текстовое поле или кнопку. Навешиваем на нее кучу фильтров, до получения нужной нам картинки.
- На слое с клипом кликаем правой кнопкой и выбираем "Copy Motion to ActionScript 3".
- Вставляем куда-нибудь то, что скопировалось в буфер - например, тут же в редактор Actions.
- Находим там блок <filters>...</filters>
- Копипастим его себе во Flex-код, в контейнер тега нужного нам визуального компонента.
- Заменяем filters на mx:filters и filters:BevelFilter на mx:BevelFilter. (у mx:filters может быть другой префикс - зависит от компонента)
- Компилируем и получаем картину, аналогичную CS. Дотюниваем, если необходимо, параметры.
четверг, октября 01, 2009
Мой дорогой блог...
вторник, июля 28, 2009
Генерим облака
А тут красоты всякой - видимо-невидимо.
Сразу хочу отметить полезный тул: Perlin Noise Explorer. Собственно, кто еще недопонял, что такое perlin noise, может подробно изучить это явление.
Замечательный пейзажик: Actionscript 3.0 perlinNoise method.
Облака с перспективой: Clouds.
Целый движок: Perlin Clouds and Frocessing (with an F).
Без демки, но проверены:
Generating Pseudo Realistic Clouds In Flash (AS3 + Perlin Noise)
Lets make some (perlin) noise!
Не облака:
Забавная пружинка: тут.
Нереальные игры с электричеством: тут.
Красивое облако: тут.
Земля: Papervision3D clouded planet Earth tutorial and source.
Такие вот пузыри: Actionscript 3 blobs / lava lamp effect
Древесные кольца: тут.
Да... Всё красиво, но мне, увы не подошло. Идея такова, что нужно генерировать небольшие клочки облаков, а для этого нужно на полученную текстуру наложить маску, плавно описывающую область. По всей видимости, времени не хватит. Вставлю картинками.
* * *
Решил поступить так. Берем пример Generating Pseudo Realistic Clouds In Flash (AS3 + Perlin Noise). Подстраиваем параметры таким образом, чтобы облака были редкими.
Для большой области, динамический рендер по производительности просто убийственный. Но мы генерируем крупный битмап один раз, не скупясь на качество, и затем, просто скроллим его циклически.
* * *
Сделал еще проще. Полученный битмап не скроллю, а циклически со смещением заливаю им нужную область. Это гораздо удобнее, т.к. метод заливки beginBitmapFill умеет склеивать текстуру самостоятельно при любом смещении. И по производительности это выигрышнее.
* * *
В примере, полученый клип с облаками накладывается с эффектом blendMode = "screen". Для производительности это не есть хорошо. Поэтому, в целях оптимизации, рабочий битмап делаем прозрачным, заливаем белым цветом и копируем в его альфа-канал любой из цветовых каналов сгенерированного битмапа с облаками. Точнее, для генерации perlinNoise используем один канал, который потом и копируем.
понедельник, июля 27, 2009
MPS, MIoC и утро испорчено
Но тут мозг натыкается на незнакомые сочетания букв. Таак. Мифы MPS. Явно не про мазду. MPS... MPS, что-то википедия ерунду выдает. Ладно, читаем дальше. Ну пипец, ни одной ссылки, будто и правда все всё знают, а я в мазде. Ага, это редактор. Попался, голубчик. От оно чо - Meta Programming System. Вот и википедия сразу разродилась. Ну в общем всё ясно. Шагай в будущее с MPS первой версии. Для чего оно нужно? Для создания и работы с DSL (опять неоднозначные аббривиатуры - это не про модем, это Domain-specific language - или лучше Предметно-ориентированный язык программирования). Теперь и пост про мифы можно почитать.
Что еще у нас интересного на сегодня? Ага, injun до Swiz добрался. Забавный принцип. Про паззлы понравилось, хоть никогда их и не любил - скучное занятие.
Все похвалили MIoC. Вот, спасибо, для тех кто в мазде - разшифровка (Metadata-driven autowire IoC framework для ActionScript 3). Про IoC знают многие, а вот MIoC - не думаю.
Напоследок. Случился бум Flash+Drupal. Мне так показалось, что пост Flash на Drupal произвел неизгладимое впечатление на Flex Constructor, и в течение последующих 3,5 часов он выдал Flex+Drupal=... C интеграцией flash и CMS сталкивается почти каждый flash-разработчик. На моей практике, сводится она к тому, что либо сервер диктует формат обмена данными, либо это делаю я сам. Второе чаще. Здесь же этот процесс систематизируется и ставится на рельсы, по которым очень скоро покатятся составы, полные готовых drupal-модулей для flash-сайтов, flash-приложений, flash-виджетов и flash-т.п. Идея популяризации Drupal очевидна.
Всё. Утро еще не кончилось, и мозги уже дымятся. А ведь еще завал работы...
четверг, июня 04, 2009
Ух ты! Binding
Вот к примеру, обычно мы делаем вот так:
<someComponent someAttribute="{someValue1+'_splitter_'+someValue2}"/>
А оказывается можно и так:
<someComponent someAttribute="{someValue1}_splitter_{someValue2}"/>
Выбираем движок для просмотра Flash-панорам
Для начала - немного теории панорам: Панорамная фотография, BASICS (здесь же можно найти и другую информацию про панорамное фото, софт, вьюверы).
По flash-вьюверам панорам, Гугл выдал следующих претендентов:
- Flash Panorama Player - платный, недорогой вьювер кубических панорам. Принцип прост - имя swf-файл вьювера должно соответствовать имени jpg-файлов, которые имеют соответствующие сторонам куба суффиксы.
- Ryubin's Flash Panorama Laboratory - Отличный движок, без исходников, но настраиваемый через XML.
- krpano - платный, недорогой вьювер с кучей дополнительных фич, типа эффект линз и тп.
- PanoSalado, Spincontrol - опенсорсный движок на базе PV3 и AIR-утилита для сборки виртуальных туров. Есть и исходники и документация.
среда, июня 03, 2009
Code-behind или mx:Script?
<mx:Script source="includes/ComponentName.as"/>Каких-либо логических недостатков такого метода я не наблюдал, однако столкнулся с постоянной глючностью автокомплита AS-редактора FlexBuilder. И вот, когда меня в конец это достало, решил взять на вооружение способ Code-behind.
Про Code-behind пишут следующее:
Code Behind
Building components by using code behind
Code-Behind in Flex 2
Code-behind gotcha in Flex Builder for AIR apps
Советы новичкам
В кратце, суть проста - наш MXML компонент ComponentName не базируется напрямую на основном компоненте, например, Canvas, а на компоненте-"прослойке" ComponentNameClass (также используется суффикс -Base). Код этого компонента размещается в ComponentNameClass.as. Его класс является потомком класса того самого основного компонента (Canvas) и содержит весь необходимый AS-код.
Все компоненты, которые имеются в ComponentName.mxml и к которым нужен доступ, должны быть объявлены в ComponentNameClass.as как public. Методы и обработчики событий - public или protected.
Вообще, конечно, это очень правильный подход. Только напрягает пара фактов - нужно возиться с объявлением класса и объявлять все компоненты, с которыми необходимо иметь дело в as-файле. Если, к примеру, я вдруг передумаю использовать в MXML вместо LinkButton (а он уже объявлен так в AS-компоненте) простой Button, получу ошибку - необходимо везде сделать замену. Выход - объявлять их дальних предков или вообще интерфейсы.
А вот интересно - есть ли средства автоматизации этого процесса? Что-то типа команды "Create Code-behind Class" или при создании MXML-компонента подобная галочка. Я не нашел...
суббота, мая 16, 2009
Модули, синглтоны, Type Coercion Failed и спасение
Сегодня столкнулся с такой проблемой:
Приложение использует модули. Один из модулей содержит ComboBox.
Во время работы, подгружается то один модуль, то другой. Так вот.
При первой активации, модуль с ComboBox работает корректно. Однако, при повторной активации модуля, начинаются проблемы - при нажатии на ComboBox вылетает ошибка:
TypeError: Error #1034: Ошибка типа Coercion: невозможно преобразовать mx.managers::PopUpManagerImpl@6c0ce41 в mx.managers.IPopUpManager.
Аналогичная ошибка с компонентом List, правда немного с другими классами:
TypeError: Error #1034: Ошибка типа Coercion: невозможно преобразовать mx.managers::DragManagerImpl@6b7ec11 в mx.managers.IDragManager.
Ужасаясь перспективе просидеть в дебаге всю ночь, полез в Гугл. И тут же нашел спасение - не один я столкнулся с таким казусом:
Flex Error #1034: Type Coercion Failed: Cannot Convert Mx.managers
Вот решение (я его оформил немного поизящнее):
Нужно в коде основного приложения указать следующую строку:import mx.managers.*;DragManager;HistoryManager;PopUpManager;
Одним индусам известно, что случается с этими синглтонами после выгрузки модуля, могу предположить, что таким образом, мы принуждаем компилятор внедрять эти классы в основное приложение а не в модули. В ином случае, они внедряются в модуль, и, скорее всего, в какой-то момент теряются.
воскресенье, апреля 05, 2009
Записываем звук с помощью Red5
Как обычно бывает, с момента зарождения проекта, уходят месяцы на процесс впаривания, продажи, рисования и утверждения дизайна. И вот, наступает очередь разработчиков, и, как обычно, на flash выделяется неделя, в лучшем случае - две (какая несправедливость).
В этот раз, правда, всё было несколько иначе - разработка началась как раз примерно за неделю до моего отлета в Египет. Поэтому, пришлось сделать максимум, чтобы без меня две недели люди всё это ставили на свои рельсы. Принцип вынесения всех настроек в FlashVars решает эту проблему на раз. Главное не забыть составить подробный мануал.
Итак, мы пришли к решению, что лучше в качестве медиа-сервера использовать Red5. Процесс установки под Windows и тестирования Red5 для локальной разработки я описал здесь: Установка Red5 и всё что нужно для Red5-разработки. По сути, в этом посте изложено всё необходимое для создания минимального приложения для записи звука/видео. В качестве формата хранения звуковых данных, решили оставить FLV. Сначала планировали конвертацию FLV в MP3 на сервере, и даже были идеи как это реализовать. Но позже решили, что для нужд проекта это излишество и лишняя нагрузка на сервер. Все записи сохраняются как есть, в формате FLV, и воспроизводятся проигрывателем, который, кстати, по виду и функционалу совсем не отличается от того, что воспроизводит MP3.
С flash-частью оказалось всё слишком просто. Достаточно было использовать версию Flash 8 и AS2. За основу я взял пример из ...\Red5\swf\samples\SimpleRecorder.fla. С момента окончания разработки прошло уже около месяц и многое забылось, но вот пара важных заметок:
- Для записи, уровень тишины необходимо ставить в 0 (setSilenceLevel). Если для голосового общения, функция активности микрофона важна для экономии трафика, то при записи речи или песни это может навредить - запись будет не идентична выступлению.
- Необходимо ограничить время записи (например, по таймауту), иначе найдутся охотники заполнить дисковое пространство сервера бесполезным мусором. Хотя, конечно, правильнее это ограничение сделать на сервере.
В итоге, на выходе у меня получились две версии проигрывателей звука в форматах MP3 и FLV (можно было сделать универсальный, но времени не хватило) и рекордер звука.
На локальном Red5, под Windows, это хозяйство работало на ура. Однако, когда потребовалось поставить Red5 под FreeBSD (если не ошибаюсь), у админов возникли серьезные проблемы с настройкой нашего приложения. Подробности мне не известны, знаю только, что у них всё заработало за день до моего прилета (т.е. возились 2 недели :) ).
Такова уж особенность Open Source - конфигурация представляет собой темный лес xml-файлов, а нормальные инструменты по настройке, так чтобы галочку поставил и всё заработало - отсутствуют. Вот и выбирайте - платить за софт, или платить специалистам за настройку бесплатного софта. Но, слава Богу, всё это уже не моя забота.
* * *
Неплохая статья в тему:
Урок. Вебкамеры с Flex 3. Часть 2
воскресенье, марта 22, 2009
mx:Pause vs flash.utils.Timer. Flex
Легкое определение переменных в MXML значительно упрощает разработку:
- позволяет легко и наглядно определять их свойства и обработчики событий
- автоматически делает переменные Bindable
- позволяет их связать с другими переменными и выражениями
- делает наглядным код
Но, на сколько я понял, не все классы можно представить в декларативном виде.
Например, класс flash.utils.Timer невозможно представить в виде MXML. Компилятор выдает ошибку "Неправильное количество аргументов". Всё от того, что конструктор этого класса содержит один обязательный параметр. Как его указать, и возможно ли это, увы, я не понял.
Но есть простое решение - использовать другой класс, хорошо подходящий по своему функционалу - mx.effects.Pause:
id="somePause"
duration="2000"
effectEnd="somePause_effectEndHandler(event)"
/>
. . .
//Стартовать задержку
this.somePause.play();
. . .
private function somePause_effectEndHandler(event:EffectEvent):void {
//Обработать окончание задержки
}
четверг, марта 19, 2009
ASDoc in MXML. Правильно комментируем MXML.
Теперь, уже достаточно сроднившись с MXML, понимаю, что есть необходимость правильно его комментировать. Просматривая листинги MXML, глаз так же нуждается в разделении блоков, как и при чтении AS-кода.
Если с AS-кодом всё давно ясно (я его использую везде где надо и где необязательно), то вот с MXML хотелось бы разобраться. И поможет нам в этом статейка "ASDoc in MXML - Functional and Design Specification". Выделим основные мысли из нее.
Основные положения
В настоящее время не существует способа документировать MXML-компоненты. (Кстати, в лайфдоках про это вот что сказано: Documenting MXML files). Компилятор asdoc не обрабатывает комментарии в MXML-файлах. Но число компонентов, разрабатываемых на базе MXML неуклонно растет, поэтому поддержка в asdoc файлов MXML очень бы помогла разработчикам при создании документации.
ASDoc комментарий
Для того, чтобы ASDoc-комментарий был обработан asdoc-компилятором, необходимо указать 3 тире после <!:<!--- asdoc comment -->
Для сравнения - обычный комментарий начинается с 2-х тире.
Комментирование MXML-компонентов и компонента уровня класса
Комментарии для компонентов внутри MXML должны располагаться перед компонентами.
Комментарий компонента уровня класса должен располагаться перед корневым тегом MXML:
<!-- Standard MXML comment: events\myComponents\MyButton.mxml -->
<!---
The class level comment for the component.
This tag supports all ASDoc tags, and does not require a CDATA block.
@see mx.container.VBox
-->
<mx:VBox xmlns="http://ns.adobe.com/mxml/2009" xmlns:mx="library:adobe/flex/halo" >
<!--- Comment for button -->
<mx:Button id="myButton" label="This button has comment"/>
<!--- This comment doesn't belong to any component and will be ignored -->
</mx:VBox>
Комментарии перед тегами Script, Metadata будут игнорироваться. Перед тегами Definition, Library, Private и внутри их, комментарии так же будут игнорироваться.
Итог
В статье приводятся примеры использования ASDoc комментирования в различных его применениях. Рассматривать их подробно я не буду - всё достаточно прозрачно.
Вывод таков - MXML комментировать надо. И для этого уже существует прототип (если я правильно понял) стандарта, которого и следует придерживаться.
четверг, марта 05, 2009
Дружим Flex с Flash. Заметки: загрузка, внедрение, шрифт. Flex
Для начала, несколько заметок:
- Перенос строки в строках MXML: символ 
 - мелочь, а приятно.
- Загрузка сложных Flash-приложений в SWFLoader должна производиться в выделенный домен приложения, т.к. могут быть конфликты классов:
. . .
private function creationCompleteHandler(event:Event):void {
swfLoader.loaderContext=new LoaderContext(false,new ApplicationDomain());
swfLoader.load();
}
- Если внешнее приложение подгружается в SWFLoader, есть вероятность, что в какой-то момент SWFLoader потеряет stage, что может пагубно отразиться на функциональности этого приложения. Если приложение где-то внутри обращается к stage и не обрабатывает его недоступность, то будут генерироваться ошибки. Побороть этот недостаток я не смог - только устранив все "не защищенные" stage из внешнего приложения.
- Внедрение шрифтов. Гораздо надежнее внедрять шрифт непосредственно из TTF файла. Внедрение из файла SWF, в котором, в свою очередь, внедрен необходимый шрифт лучше оставить для тяжелых случаев несовместимостей с Flex. Дело в том, что почему-то, внедренные в SWF разные стили (normal, bold) шрифта не корректно "извлекаются" Flex-ом. Он не дает назвать разные стили разными именами (как это можно сделать в первом случае), теряет одно из начертаний (жирный шрифт просто не выводится). Возможно, это из-за особенностей конкретных шрифтов, но первый метод срабатывает гораздо стабильнее.
{
fontFamily: "Century Schoolbook";
fontWeight: normal;
fontStyle: normal;
src: url("file://./assets/fonts/CENSCBK.TTF");
unicodeRange:
U+0020-U+0040, /* Punctuation, Numbers */
U+0041-U+005A, /* Upper-Case A-Z */
U+005B-U+0060, /* Punctuation and Symbols */
U+0061-U+007A, /* Lower-Case a-z */
U+007B-U+007E, /* Punctuation and Symbols */
U+00FC-U+00FD,
U+0410-U+042F, /* Cyrillic Upper-Case A-Z */
U+0430-U+0451; /* Cyrillic Lower-Case a-z */
}
@font-face
{
fontFamily: "Century Schoolbook Bold";
fontWeight: bold;
fontStyle: normal;
src: url("file://./assets/fonts/SCHLBKB.TTF");
unicodeRange:
U+0020-U+0040, /* Punctuation, Numbers */
U+0041-U+005A, /* Upper-Case A-Z */
U+005B-U+0060, /* Punctuation and Symbols */
U+0061-U+007A, /* Lower-Case a-z */
U+007B-U+007E, /* Punctuation and Symbols */
U+00FC-U+00FD,
U+0410-U+042F, /* Cyrillic Upper-Case A-Z */
U+0430-U+0451; /* Cyrillic Lower-Case a-z */
}
- Внедрять клип из внешней SWF так, чтобы работали его фреймовые скрипты можно следующим образом:
source="@Embed(source='assets/Index.swf')"
При внедрении отдельного символа, его фреймовые скрипты и скрипты всех вложенных объектов теряются:source="@Embed(source='assets/Index.swf'#Index)"
Игра с параметром mimeType не помогает.
На управлении внедренным контентом я бы хотел остановиться подробнее. Если у нас много однотипного материала для внедрения вышеописанным способом, то плодить SWF-файлы не удобно, плюс, внедряя каждый файл, мы не можем обобщать графику - она будет внедряться для каждого файла заново (не проверял, но догадываюсь).
Куда удобнее создать одну большую библиотеку и из нее внедрять символы. Но, к сожалению, их скрипты уже будут не доступны.
Но у нас есть в распоряжении метки фреймов и имена клипов. Совмещая возможности
MovieClip.currentLabels и MovieClip.addFrameScript можно получить контроль над внедренным клипом и заставлять его в нужный момент выполнять необходимые нам действия: останавливать клип на нужном фрейме, генерировать события и даже передавать данные в текстовые поля клипа.
Создаем компонент - наследник SWFLoader. После инстанцирования класса внедренного клипа (конец метода load(), можно так же добавить и в обработчик события загрузки), считываются все его метки и в их фреймы добавляются необходимые скрипты. Имя каждой метки имеет ключевую составляющую, которая и определяет тип действия добавляемого скрипта.
В нужный момент можно заставить клип остановиться, перейти на другую метку, генерировать событие (с идентификатором, так же зашитым в имя метки), просканировать клип и получить срез всех визуальных объектов, чтобы делать с ними всё что угодно. Главное - этот момент устанавливается прямо в таймлайне клипа, а не путем каких-либо расчетов количества фреймов или подобных методов.
Прекрасный момент - праздник еще не настал, а дидлайны уже позади! Отдыхать и набираться сил.
И конечно, наших прекрасных женщин поздравляю с праздником 8 марта!
суббота, февраля 28, 2009
Модули vs. компоненты. Flex
В моем опыте Flex-разработки наступает новая стадия взросления.
Ну, условно, у себя я уже могу выделить две стадии (не считая робкого потрагивания и любопытного пощупывания):
- Код представляет собой голый MXML, на котором и построено всё приложение. Крупные вспомогательные структуры классов и обильные инклюды. В решении относительно сложных задач (либо совсем простых) я полагался только на pure AS проекты и компоненты.
- Приложение делилось на компоненты (MXML компоненты), каждое окошко, каждый функционально законченный экран были компонентами. Обильное использование компонентов значительно упростило разработку приложений и внесло строгость и порядок, несмотря на довольно пространный список в Components -> Custom.
Кроме того, такой подход значительно ускоряет разработку, уже засчет того, что визуальный редактор теперь не должен перерисовывать каждый раз всё приложение (а делает он это отнюдь не быстро).
Сегодня в разработке проект, который так и напрашивается на использование модулей. В общих чертах - это небольшой промо-сайт с тремя основными разделами. Три этих раздела мы и оформим как модули.
Руки так и зачесались попробовать создать модуль в FB. Открываю проект, создаю New->MXML Module. Открывается новый файл mxml, в который я добавляю, к примеру, кнопку, и текстовое поле. Сохраняю. В окошке Components->Custom появился новый компонент, по имени модуля.
Проведем эксперемент. Перетащим его в окно основного приложения. Всё как с обычным компонентом. Компилирую. Замечательно: скомпилировалось два swf - один с именем приложения, другой - с именем модуля.
Для любопытства, копируем один только swf приложения и запускаем: видим кнопку и текстовое поле. Как я и предполагал, наш модуль включен в состав swf приложения как обычный компонент.
Запустим swf модуля. Сразу получаем ошибку "Не удалось найти класс mx.core::SpriteAsset." И не мудрено - модуль не содержит классов, включенных в основное приложение.
Но нам-то от модуля нужно что? Чтобы он не был включен в приложение, а подгружался в процессе работы приложения. Хотя, возможность использовать модуль как обычный MXML-компонент тоже надо отметить.
Ознакомимся вкратце с документацией: Creating Modular Applications. Здесь всё, на достаточно понятном языке, достаточно подробно разжевывается.
Итак. Нас интересовали загрузка модуля и ее мониторинг.
Пожалуйста, смотрим: Loading and unloading modules. За загрузку отвечает класс ModuleLoader. Любопытно, что это наследник VBox. Непонятно, почему именно VBox, а не, к примеру, HBox. Уж я-то вообще ожидал увидеть в этой роли SWFLoader. Ну да ладно. Убираем из кода приложения модуль и вставляем ModuleLoader. Кстати, он присутствует в палитре компонентов Layout.
Вписываем в свойство url имя файла модуля. И что особенно приятно, визуальный редактор сразу отобразил содержимое модуля. Вводим имя другого модуля - пожалста! Отображается другой модуль. Запускаем - всё замечательно отображается и работает.
Теперь по поводу мониторинга. Смотрим Using ModuleLoader events. ModuleLoader генерирует следующие события: setup, ready, loading, unload, progress, error, и urlChanged. Но позвольте! Если progress мы наблюдаем в этом списке, то почему нет open и complete? Что помешало вместо loading генерировать open, а вместо ready - complete?
При таком раскладе, если я использую ProgressBar в режиме mode="event", загрузка успешно мониторится, но ProgressBar не генерирует событие complete, что в некоторых случаях было бы полезно. Ну что ж, никто не мешает нам устранить этот недостаток, создав своего потомка ModuleLoader. Дело поправимое.
Есть еще один компонент, управляющий загрузкой модулей: ModuleManager. Этот класс, как нам обещают, предоставляет больше возможностей по управлению загрузкой модулей чем предыдущий. Но при этом, как утверждается, техника его использования является менее абстрактной чем работа с ModuleLoader.
Да, разработчики Flex не перестают меня удивлять. ModuleManager наследуется от Object и содержит всего два статических метода, что ввело меня в небольшой ступор. Однако, после изучения предложенных примеров, всё встало на свои места. Метод ModuleManager.getModule возвращает объект, удовлетворяющий интерфейсу IModuleInfo, уникальный для каждого управляемого модуля. Этот объект, в дальнейшем, можно использовать для загрузки модуля (метод load) и мониторинга событий загрузки, а затем, для инстанцирования модуля (через свойство factory).
Более подробное изучение этого класса, погружает нас в глубины Flex, что в мои планы пока совсем не входит. Вот уж, другими словами и не скажешь - все намного менее абстрактно. И больше подходит для решения специфических задач.
Ну-с, добро пожаловать в мир модульных приложений. Начинаем действовать!
* * *
Впечатления. Работа с модулями не разочаровала: стабильно и надежно. Единственные проблемы, с которыми я столкнулся:
- Внедрение шрифта. CSS с внедрением TTF-шрифта определяется в главном приложении. Подгружаемые модули успешно используют эти шрифты. Но, возникла проблема с внедряемыми SWF, в которых используется другой шрифт. При вводе в динамические поля, ничего не отображалось. Тогда я внедрил этот шрифт в модуль. Шрифт стал отображаться. Но, что интересно, когда я собрал Release Build, шрифт опять перестал отображаться. Пришлось оставить Debug-версию модуля. Но это повлекло за собой следующую проблему.
- Если основное приложение собрано в Release Build, оно некорректно подгружает модуль, собранный в Debug Build. Я думаю, что вообще, по-отдельности модули лучше не обновлять. Я обратил внимание, что размер SWF-файла модуля даже при небольших изменениях, при перекомпиляции заметно меняется. Поэтому, следует, наверное, соблюдать осторожность при компиляции и обновлении модулей.
среда, февраля 25, 2009
В цинковом гробу. Перетаскиваемые окошки
Во-первых, сразу зарекаюсь - Мак только для мак-девелоперов. Без меня. Такого количества проблем я уже давно не встречал. Возможно, основным виновником их является Zinc, который я смело могу назвать УСЛОВНО кросс-платформенным.
Что сказать про Zinc 3.0? Под красивым брендовым дизайном, симпатичной оболочкой, красивыми заголовками скрывается довольно ограниченный функционал, убогая документация и море непонятностей, глюков и граблей.
В данном посте, приведу один пример, как простая задача решается через "заднее место".
Нужно, чтобы окошко нашего виджета перетаскивалось мышкой за специальную панельку. В документации, нам рассказывают про это так: Creating a Draggable Form. И что мы получаем? Да полный отстой. Мышь теряет окошко, потом, при наведении вдруг опять подхватывается, уже без нашего на то соизволения, в общем, ужас. Как это победить? Нужно повесить 3 обработчика мыши на панельку и сделать это вот как:
dragNDropRenderer.addEventListener(MouseEvent.ROLL_OVER, rollOverHandler);
dragNDropRenderer.addEventListener(MouseEvent.ROLL_OUT, rollOutHandler);
dragNDropRenderer.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
. . .
private function rollOverHandler(event:MouseEvent):void {
mdm.Forms.getFormByName("MainForm").startDrag();
}
private function rollOutHandler(event:MouseEvent):void {
if (!event.buttonDown) {
mdm.Forms.getFormByName("MainForm").stopDrag();
}
}
private function mouseUpHandler(event:MouseEvent):void {
mdm.Forms.getFormByName("MainForm").stopDrag();
}
Конфликт событий мыши распространяется только на нажатие. Отпускание, вполне корректно работает. Кстати, при перетаскивании, обрабатывать нажатие вообще не советую - реакция совершенно непредсказуема. Таким образом, мы отрубаем перетаскивание пир отпускании кнопки, а при отведении мыши от панели проверяем, отпущена ли в данный момент кнопка. Если отпущена - останавливаем перетаскивание. Если нет - ни в коем случае этого не делаем - мышь потеряет окошко в момент таскания.
Другие баги - почему под MacOX криво работает LocalConnection, или не открываются Zinc-ом новые окошки, и не распарсивается полученный с сервера XML, мне еще предстоит выяснить. Чувствую, это будут "приятные" сюрпризы.
* * *
В обработчик отпускания мыши добавлена проверка на отсутствие мыши в области панели.
* * *
Продолаются жалобы. Под MACOX не удалось (под Windows всё Ок) передать на сервер запрос с GET-параметрами (URLRequest). Запрос проходит, параметры не передаются. Не имел возможности выяснить, виновен ли в этом Zinc или админы сервера. В итоге, стали передавать параметры через POST, что сразу дало положительный результат.
* * *
Прозрачность. Плашка прозрачностью 1% ложится поверх поверхности со сложным изображением сложной прозрачности. Окно приложения устанавливается прозрачным. И что вы думаете? Эта плашка видна. Она как бы добавляет прозрачности подлежащему изображению. То же самое можно сказать, если поверх ложится растр с прозрачностью. Прозрачная область растра становится видна.
Выход - не допускать "недопрозрачностей", обтравливать растр во флэше.
* * *
Всё. Финиш. Zinc и MacOX - больше несовместимые понятия. Делаю полноэкранное приложение. В окне приложения, справа, где-то на 1/4 ширины, существует "мертвая" зона, в которой мышь перестает оказывать воздействие на интерактивные flash-элементы. Нет, нельзя сказать что совсем не оказывает. После 5-10 нажатий, кнопка срабатывает. Но это же бред. Элементраный пример - делаем во flash плашку размером с экран (1280x800), вставляем SWF в гроб, билдим и наблюдаем эту границу. Кошмар. Под Windows и под MacOX в Safari работает превосходно.
Сделать многооконное приложение с Zinc также не получилось - опять же проблемы с мышью. Интерактив не откликается.
среда, февраля 11, 2009
Как отображать шрифт без сглаживания (bitmap text) во Flex
Если во Flash CS, мы можем просто так взять, да и указать тип рендеринга шрифтов "Bitmap text" (без антиалиасинга) и иметь полноценное отображение текста с неполной прозрачностью, наклоном и т.п., то во Flex мы можем только управлять параметрами сглаживания шрифта, или не внедрять шрифт совсем (тогда о прозрачности не может быть и речи).
Но если мне, всё-таки, нужен именно несглаженный полупрозрачный шрифт?
Проблема решается, как и многие другие во Flex, через "одно" место.
В лайфдоках, находим такую статейку: Embedding fonts from SWF files. Здесь рассказывается вообще о внедрении шрифта с использованием Flash CS. Пользуясь таким методом, можно внедрить любой шрифт, поддерживаемый Flash CS.
Однако, здесь не сказано ни слова про внедрение шрифта Bitmap text (без антиалиасинга). И вообще, в документации Flex, про это как-то совсем ничего нет. А ведь это странно и непонятно - Flex-приложения как раз направлены на отображение данных, а всем известно, что данные отображаются лучше несглаженным шрифтом. К чему тогда все эти эффекты с фэйдом и прочими трансформациями, если невнедренный шрифт их не отображает.
Нам на помощь приходит статья всеобщего друга всех флэшеров GSkinnerа Bitmap Fonts in Flex (via Flash). Правда, в ней всё несколько усложнено, но, подозреваю, что это из-за того, что писалось это для Flex 2. Ну а мы то уже на Flex 3, поэтому всё немного проще. Идея в том, что шрифт, внедренный как Bitmap text, меняет название в некую неприглядную форму, типа "Tahoma_12pt_st".
Итак, к чему мы пришли (опишу вкратце мои действия):
1. Создаем SWF-файл fonts.swf (можно любой другой). Версия Flash 9, ActionScript 3.0. Во всех статьях создается файл версии Flash 8, но, почему-то, у меня такой файл Flex не подцеплял/ - не может оттранскодить.
2. Создаем текстовые Dynamic-поля, в каждое из которых добавляем хотя-бы один символ нужного нам начертания. Соответственно, если все начертания нам нужны, то будет 4 текстовых поля: Normal, Bold, Italic, Bold Italic.
3. Устанавливаем размер шрифта, который мы будем использовать в Flex-приложении. Дело в том, что в приложении, корректно может быть отображен только один размер внедренного шрифта - тот который мы сейчас укажем. Если указать другой размер, шрифт некрасиво размажется. Я указываю 12.
4. Указываем в Embed... диапазоны, которые нам надо внедрить.
Кстати, можно пойти другим путем и, вместо текстовых полей, создать в библиотеке 4 символа-шрифта (New font...) и всё будет точно так же, за исключением того, что шрифт внедрится весь - без ограничений, что плохо для объема.
5. Компилируем и добавляем в папку проекта.
6. В CSS файле проекта (я отвел для этого специальный файл fonts.css) указываем следующий код:
@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: normal;
fontWeight: normal;
}
@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: normal;
fontWeight: bold;
}
@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: italic;
fontWeight: normal;
}
@font-face {
src: url("file://./assets/fonts.swf");
fontFamily: "Tahoma_12pt_st";
fontStyle: italic;
fontWeight: bold;
}
7. Теперь, мы можем в любом стиле указать:
fontFamily: "Tahoma_12pt_st";
fontSize:12px;
fontAntiAliasType:normal;
}
Важно указать параметр fontAntiAliasType:normal. Если этого не сделать, шрифт в некоторых случаях будет отображаться размыто, а если это выделяемый текст - при его выделении будет твориться что-то невообразимое.
Ну и конечно, не забыть уточнить размер шрифта - иначе всё поедет.
8. Ну и собственно, применяем этот стиль к компоненту:
width="100%"
styleName="Regular"
>
<mx:htmlText><![CDATA[<b>Максимальный</b> размер загружаемого файла — 3 Мб. Допустимые форматы: GIF, JPG, BMP, TIFF, PNG.]]>></mx:htmlText>
</mx:Text>
Если нам понадобится шрифт другого размера - уж не поленитесь, повторите всё со второго пункта - так уж положено.
* * *
Да, забыл добавить про то, что здорово помогает в разборках со шрифтами такой кусочек кода (взят из статьи):
var fontList:Array = Font.enumerateFonts(false);
for (var i:uint=0; i<fontList.length; i++) {
trace("font: "+fontList[i].fontName);
}
понедельник, февраля 09, 2009
Прогресс-бар на любой вкус. Flex
Сделать прогресс-бар (ProgressBar) совершенно не похожим на постепенно заполняющуюся горизонтальную полосу.
Скинирование позволяет заменить лишь изображения не залитой и залитой полос. Ну а если мне не нужна полоса?
Порыскав по интернету, пришел к выводу, что все усиленно заморачивались на проблему подмены предзагрузчика flash/flex-приложений, а вот видоизменить ProgressBar, почему-то никому не понадобилось.
Ну что ж, раз готового материала не нашлось, придется мастерить ручками.
Продолжение следует...
пятница, февраля 06, 2009
Неэффектные эффекты. Flex
По началу, сделал просто появляющуюся/исчезающую панель, используя ее свойства showEffect/hideEffect. По событию наведения мыши делал visible=true, при отведении - наоборот. Эффекты:
<mx:Fade id="PanelFadeIn" alphaFrom="0" alphaTo="1" duration="400"/>
<mx:Fade id="PanelFadeOut" alphaFrom="1" alphaTo="0" duration="400" startDelay="1000"/>Полная фигня получилась. Эффекты конфликтовали и панель появлялась и исчезала непредсказуемым образом.
Чтобы образумить эффекты, пришлось их останавливать (stop()) перед тем как переключать visible. Так более-менее заработало.
Попробовал другой способ - есть два стэйта, в которых панель находится в разных положениях. При наведении на контейнер мыши, стейт сменяется и панель перемещается в другое место, при отведении - возвращается на прежнее.
Сначала применил свойство moveEffect, в которое указывается имя эффекта <mx:Move id="PanelMotion" /> Получаю опять ерунду. В начале вроде бы всё корректно - уезжает, приезжает, но после нескольких таких движений, что-то там начинает заедать. Метод не годится.
Применяем другую тактику - используем transitions. Сразу всё встает на свои места:
<mx:transitions>
<mx:Transition fromState="Normal" toState="PanelIsShown">
<mx:Move duration="200" target="{сontrolPanel}"/>
</mx:Transition>
<mx:Transition fromState="PanelIsShown" toState="Normal">
<mx:Move duration="200" target="{сontrolPanel}"/>
</mx:Transition>
</mx:transitions>
Можно конечно обойтись одним блоком fromState="*" toState="*", но в некоторых ситуациях, панель "промигивает" в неположенных местах. Но это, конечно, зависит от специфики конкретного приложения.В итоге, появление/убирание панели сделать средствами Flex удалось, но не так, как хотелось бы. Дело в том, что я хотел сделать небольшую паузу перед тем, как панель уберется. Сделал я следующее: второй блок transitions заменил на:
<mx:Sequence target="{сontrolPanel}">
<mx:Pause duration="1000"/>
<mx:Move duration="200"/>
</mx:Sequence>
Это вызвало две идиотские проблемы:
1. Такой способ наотрез отказывается работать, если в state меняется не непосредственно координата, а, к примеру, свойства right/left: <mx:SetStyle target="{сontrolPanel}" name="right" value="50"/> - анимация просто отсутствует.
2. Панель полностью исчезает и снова появляется, если быстро убрать мышь и опять навести ее на контейнер. А по-хорошему, панель должна оставаться на месте.
* * *
В общем, решая совсем простую задачу, я столкнулся с кучей дурацких проблем, которые, возможно, решаемы, но скорее всего через шаманские средства - наследование классов эффектов и модификация методов этих классов под свои нужды.
Или я что-то не допонял, или работа с эффектами оставляет желать лучшего...
Разочарован :(
* * *
Вот пример с аналогичной панелькой:
Sliding Canvas with Flex. Исходный код тут. Работает вполне стабильно. Замечательно. И главное, у меня такие штуки проходили почему то криво... Сам виноват. Поленился сделать такую же проверку transitionHappening. А проверял свойство isPlaying, а оно как-то не правильно показывает если стоит startDelay. Другой подход с принудительной остановкой stop() тоже не проходит - надо было изначально блокировать переключение visible, как в примере. А всё лень виновата - добавлять лишние скрипты не хочется :).
Хотя, с другой стороны, управлять положением компонентов через механизм стэйтов правильнее (универсальнее).
* * *
В итоге, всё получилось с применением showEffect/hideEffect. Получилось вполне стабильно и без неприятных побочных эффектов:
public function hideControlPanel():void {
panelShowEffect.stop();
panelHideEffect.stop();
if (controlPanel.visible)
controlPanel.visible=false;
}
public function showControlPanel():void {
if (!this.enabled) return;
panelShowEffect.stop();
panelHideEffect.stop();
if (!controlPanel.visible)
controlPanel.visible=true;
}
. . .
<mx:canvas width="{controlPanel.width}" height="100%" clipcontent="true" rollover="showControlPanel()" rollout="hideControlPanel()" creationcomplete="hideControlPanel()" backgroundcolor="#FFFFFF" backgroundalpha="0">
. . .
<mx:Move id="panelShowEffect" xTo="0" duration="200"/>
<mx:Move id="panelHideEffect" startDelay="1000" duration="200" xTo="{-controlPanel.width}"/>
. . .
<mx:VBox
id="controlPanel"
height="100%"
showEffect="{panelShowEffect}"
hideEffect="{panelHideEffect}"
x="{-controlPanel.width}"
visible="false"
>
. . . Содержимое панели . . .
</mx:VBox>
. . .
</mx:Canvas>
Единственная проблема -пришлось отказаться от эффекта WipeUp/Down, примененного к компоненту, вложенному в выезжающую панель, из-за его нестабильной работы.
вторник, января 27, 2009
Неубиваемый звук в режиме Start. AS3
Приложение загружает один и тот же SWF в разные контейнеры, каждый из которых проигрывает загруженный клип и имеет автономное управление звуком. В таймлайне SWF стартуется звук в режиме Start.
Контейнеры добавляются (mx:AddChild) в разных стэйтах (mx:State). Соответственно, при переключении стэйтов, я отслеживаю события addedToStage/removedFromStage для остановки/запуска клипа и включения/выключения звука (компоненты при смене стэйтов удаляются из списка отображаемых объектов, а не из памяти). Если не останавливать клипы, они всё равно воспроизводятся, даже если их нет в списке отображаемых объектов, а так же и их звук, что, понятное дело, совсем не хорошо.
Так вот. При старте звука в режиме Start в одном контейнере, в другом этот звук уже не начнет воспроизводиться заново, а будет продолжать играться. Регулировка громкости так же будет влиять только на него. В остальных режимах, дело ясное, всё работает независимо.
Остановка таймлайн-звука для конкретного клипа в AS3 не предусмотрена.
Есть возможность отключить все звуки приложения при помощи SoundMixer.stopAll();. Как вариант, такой подход в принципе, приемлем, но остановить все звуки приложения - это значит исключить ситуацию, когда, к примеру, требуется остановить звук лишь одного компонента.