Во Flash CS4 есть возможность экспортировать анимацию в виде ActionScript кода. Суть, в том, что можно сделать анимационных шаблонов и использовать их в проектах. Особенно это может быть важно при взаимодействии дизайнера и программиста - дизайнер может сделать анимацию именно так как ему надо. А программист, может легко её использовать, вставив в нужный кадр или класс. Экспортированный код использует классы из SWC библиотеки поставляемой с Flash CS4, а значит, его можно использовать за пределами Flash IDE. Такая возможность переноса анимации может быть полезна программистам, которые используют "нормальную" среду разработки/кодирования.
Но оказалось, что другие IDE, компилирующие SWF приложение самостоятельно, вызывают ошибки при использовании этой библиотеки. Эти ошибки происходят из-за того, что в библиотеке использованы специфичные для Flash IDE подходы:
- В качестве контейнера для анимируемого объекта должен быть экземпляр класса
MovieClip(или его наследник). - В контейнере обязательно должно быть объявлено свойство с таким же именем, как у анимируемого объекта(свойство
DisplayObject.name).
Дополнительно к этому, библиотека проверяет наличие корректных значений свойств parent у анимируемого объекта и root у его контейнера, на случай если объект удалён со сцены. Если одно из этих свойств не содержит значения, то библиотека остановит проигрывание анимации.
Если станет необходимость использовать данную библиотеку не только во Flash CS4, то есть два варианта развития событий - соблюдение этих правил или адаптация библиотеки. Есть, конечно, ещё варианты - изменить библиотеку изнутри или не использовать её вовсе, но они обсуждаться не будут.
Соблюсти правила не составит проблем, если заранее быть к этому готовым. Но, если нет возможности использовать объекты типа MovieClip в качестве контейнера? Я предлагаю два подхода использования такой анимации. Оба подхода основаны на обмане библиотеки - подмене настоящего контейнера, на фальшивый контейнер типа flash.display.MovieClip.
Адаптация библиотеки
Суть подхода в том, чтоб расширить необходимые классы и создать условия для использования библиотеки. Достаточно расширить один метод, чтоб избежать проблем. При внедрении анимации из Flash CS4, единственное, что нужно будет сделать, это заменить оригинальные классы на адаптированные.
Класс создающий необходимые условия:
package com.actualwave{ import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import flash.display.MovieClip; import flash.events.Event; public class FakeParentClip extends MovieClip{ static public var defaultDefinition:Class = FakeParentClip; static public const NAME:String = 'target'; static public const TARGET_ERROR:String = "Target can not be added twice."; protected var _target:DisplayObject; public function set target(child:DisplayObject):void{ if(this._target) throw new Error(TARGET_ERROR); this._target = child; child.addEventListener(Event.REMOVED_FROM_STAGE, this.removedFromStageHandler); } protected function removedFromStageHandler(event:Event):void{ this._target.removeEventListener(Event.REMOVED_FROM_STAGE, this.removedFromStageHandler); this._target = null; } public function get target():DisplayObject{ return this._target; } public function removeItemByName(name:String):void{ delete this[name]; } override public function get root():DisplayObject{ return this; } } }
Этот класс подменяет свойство root и создаёт свойство с таким же именем, как у анимируемого объекта.
Класс расширяющий fl.motion.AnimatorFactory3D
package com.actualwave{ import fl.motion.AnimatorBase; import fl.motion.AnimatorFactory3D; import fl.motion.MotionBase; import flash.display.DisplayObject; public class AnimatorFactory3D extends fl.motion.AnimatorFactory3D{ protected var _parent:FakeParentClip; public function AnimatorFactory3D(motion:MotionBase):void{ super(motion); _parent = new FakeParentClip(); } override public function addTarget(target:DisplayObject, repeatCount:int = 0, autoPlay:Boolean = true, startFrame:int = -1, useCurrentFrame:Boolean = false):AnimatorBase{ if(!target || !target.parent) return null; var parent:FakeParentClip = new FakeParentClip.defaultDefinition(); parent.target = target; var animator:AnimatorBase = addTargetInfo(parent, FakeParentClip.NAME, repeatCount, autoPlay, startFrame, useCurrentFrame); return animator; } } }
Заменяется всего один метод - AnimatorFactory3D.addTarget(), в нём создаётся фальшивый контейнер и передаётся дальше. После импорта анимации, необходимо только заменить пакет класса
import fl.motion.AnimatorFactory3D;
на
import com.actualwave.AnimatorFactory3D;
И анимация будет работать.
Подмена родительского класса
Этот подход может показаться более удобным для пользователей Flex framework. В данном подходе происходит почти то же самое, что и в предыдущем, за исключением того, что необходимые изменения вынесены наружу.
Класс создающий необходимые условия:
package{ import flash.display.DisplayObject; import flash.display.DisplayObjectContainer; import mx.core.Application; import mx.core.UIComponent; import mx.flash.UIMovieClip; [DefaultProperty("contentChild")] [DefaultProperty("contentChildren")] public dynamic class FakeAnimationContainer extends UIMovieClip{ static public const instance:FakeAnimationContainer = new FakeAnimationContainer(); protected var _root:DisplayObjectContainer; public function FakeAnimationContainer():void{ super(); _root = Application.application as DisplayObjectContainer; } override public function get root():DisplayObject{ return _root; } override public function addChild(child:DisplayObject):DisplayObject{ this[child.name] = child; return child; } override public function addChildAt(child:DisplayObject, index:int):DisplayObject{ this[child.name] = child; return child; } override public function removeChild(child:DisplayObject):DisplayObject{ delete this[child.name]; return child; } override public function removeChildAt(index:int):DisplayObject{ throw new Error('Not implemented.'); return null; } public function set contentChild(value:UIComponent):void{ this.addChild(value); } public function set contentChildren(list:Array):void{ for each(var p:* in list) this.addChildAt(p, 0); } } }
Использование:
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" preinitialize="{preinitializeHandler(event)}" xmlns:local="*"> <mx:Script> <![CDATA[ import fl.motion.AnimatorFactory3D; import flash.geom.Vector3D; import fl.motion.MotionBase; import flash.filters.*; import flash.geom.Point; private var __motion_Symbol1_6:MotionBase; protected var __animFactory_Symbol1_6:AnimatorFactory3D; protected function preinitializeHandler(event:Event):void{ if(__motion_Symbol1_6 == null) { __motion_Symbol1_6 = new MotionBase(); __motion_Symbol1_6.duration = 80; // ряд значений в виде __motion_Symbol1_6.addPropertyArray(property, [values]); __animFactory_Symbol1_6 = new AnimatorFactory3D(__motion_Symbol1_6); __animFactory_Symbol1_6.transformationPoint = new Point(97.250000, 63.850000); __animFactory_Symbol1_6.transformationPointZ = 34.850000; /** FakeAnimationContainer использует один глобальный экземпляр и его * можно использовать вместо постоянного создания новых экземпляров. * FakeAnimationContainer.instance.addChild(this.panel); */ } } ]]> </mx:Script> <mx:Panel id="panel" name="panel" title="Test flying panel" width="200" height="200" x="200" y="200"> <mx:Button label="Animate me!" click="{__animFactory_Symbol1_6.addTargetInfo(this.animationParent, 'panel', 0)}"/> </mx:Panel> <local:FakeAnimationContainer id="animationParent" contentChild="{this.panel}"/> </mx:Application>
Следует обратить внимание, что используется метод AnimatorFactory3D.addTargetInfo(), в котором необходимо указать объект контейнер и свойство содержащее ссылку на анимируемый объект.
Для примера, можно посмотреть проекты для Flex Builder 3, реализующие три подхода использования анимации из Flash CS4:
Как использовать примеры:
Для начала необходимо подключить библиотеку к проекту, она поставляется в виде файла SWC и исходного кода.
Путь к библиотеке
Adobe Flash CS4 folder\Common\Configuration\ActionScript 3.0\libs\flash.swc
Путь к исходным файлам библиотеки
Adobe Flash CS4 folder\Common\Configuration\ActionScript 3.0\projects\Flash\src\
Выберите, что роднее.
Для импорта анимации в проект, необходимо получить ActionScript код из анимации, а для этого необходимо кликнуть правой кнопкой мыши по любому кадру необходимой анимации(или по анимируемому объекту) и выбрать пункт "Copy Motion as ActionScript 3.0..." из контекстного меню. Готовый код копируется в буфер обмена и после этого его можно вставить в необходимый MXML или AS файл.
Код анимации необходимо немого изменить, перед использованием.
- Перенести объявление переменных из локальных в члены класса.
- Добавить анимируемый объект, как советуют в комментариях к коду.
Использовать один из вышеперечисленных подходов.
В итоге, может получится что-то совсем не прохожее на мой пример.
Метки: ActionScript 3, animation, export, Flash CS4, Flex, import
Добрый день!
У меня небольшой трабл. Надеюсь, что поможете.
Анимация во flex ( as project ) отличается от той что проигрывается в cs4. такое ощущение что настройки камер отличаются… завел словарь с теми параметрами. проигарл их onEnterFrame результат тот же… как сделать идентичные анимации?
я добавляю объект подвергающийся трансформации в главном файле приложения:
cv = new cardView();
addChild(cv);
_buildMotionBase();
var an:AnimatorFactory3D = new AnimatorFactory3D(__motion_cardView_2);
an.addTarget(cv);