利用FLEX 4中的Animate来自定义effect 特效
此次AJSPlayer的开发过程中,由于将会使用到大量的,高度自定义的特效,而Flex 4中原始提供的封装特效组件(如Move、Rotate、Fade,甚至包含对应的3D特效等等)已经不能满足我们的需求了,而这个时候就需要来自定义一些effect特效。 在Flex 4里,effect特效可以应用于任意类型的对象和属性(Interpolator是这一环节中较为关键的一个东西,Adobe称之为‘补插器’,后面将会有详细介绍),这是Flex 4为我们带来的最炫目的新特性之一。 Flex4里的所有特效类都继承于Animate,而Animate同时还继承于Effect。Flex4里的特效类的层次是与Flex3大不相同,它提供了更强大,自由度更高的特效定义。当然,同时也变得更为复杂。 首先,我们以Move特效做为例子来了解一下Flex 4中的特效。 motionPaths(MotionPath类型的数组)又是什么?它的字面意思是“运动路径”,查看MotionPath源码注释又看到这样的解释:“MotionPath 类定义效果的 Keyframe 对象的集合,以及要设置动画的目标上属性的名称。每个 Keyframe 对象都定义位于效果过程中某个特定时间的属性的值。这样,效果就可以通过在两个关键帧所指定的值之间进行插补来计算目标属性的值。” 重点来了。Interpolator是IInterpolator的一个实现,FLEX 4定义了几种Interpolator,包括NumberInterpolator、RGBInterpolator、HSBInterpolator、MultiValueInterpolator。而我们最常用的则是前面两个。animate在播放时,会自动的去调用这些插补器来计算出MotionPath的关键帧,实现动画效果,通常我们是不需要定义的。但是,有时候,比如,我们希望物体能做圆周运动,这个时候我们通常的做法是利用timer去不断的更新根据公式所计算出来的xy坐标。而自定义一个Interpolator则可以更方便的为我们解决这一问题。 看下面OvalInterpolator.as的代码: package com.effects { import mx.resources.IResourceManager; import mx.resources.ResourceManager; import spark.effects.interpolation.IInterpolator; import spark.effects.interpolation.NumberInterpolator; public class OvalInterpolator extends NumberInterpolator { private var _width:Number; private var _height:Number; private var _type:String; private var _centerPrintX:Number; private var _centerPrintY:Number; public function OvalInterpolator(type:String) { super(); _type=type; } /** * @private * Used for accessing localized Error messages. */ private var resourceManager:IResourceManager = ResourceManager.getInstance(); override public function interpolate(fraction:Number,startValue:Object,endValue:Object):Object { if (fraction == 0) return startValue; else if (fraction == 1) return endValue; if ((startValue is Number && isNaN(Number(startValue))) || (endValue is Number && isNaN(Number(endValue)))) throw new Error(resourceManager.getString("sparkEffects","cannotCalculateValue",[startValue,endValue])); return computeInterpolate(Number(startValue) + (fraction * (Number(endValue) - Number(startValue)))); } private function computeInterpolate(angle:Number):Number{ switch(_type) { case "x": { return (_centerPrintX+ _width - _width * Math.cos((angle) * Math.PI / 180)); } case "y": { return (_centerPrintY+ _height * Math.sin((angle) * Math.PI / 180)); } default: { throw new Error(resourceManager.getString("sparkEffects","不被预知的参数类型",[_type])); } } } public function get width():Number { return _width; } public function set width(value:Number):void { _width = value; } public function get height():Number { return _height; } public function set height(value:Number):void { _height = value; } public function get type():String { return _type; } public function get centerPrintX():Number { return _centerPrintX; } public function set centerPrintX(value:Number):void { _centerPrintX = value; } public function get centerPrintY():Number { return _centerPrintY; } public function set centerPrintY(value:Number):void { _centerPrintY = value; } } }
而前面所提到AnimateTransform的工作其实就是为我们定义并封装了motionPaths,并且按照根据需要实现特效的属性指定对应类别的插补器,相当于为其做了一个“归类”的操作。Flex 4中的所有封装的顶层特效,都有与AnimateTransform类似,但是管理着不同类型或种类的对象及属性的父类,他们都会将其做为一个实例赋给Animate,以实现严格的归类特效。 也许文字描述过于抽象或枯燥,下面看完整demo代码: package com.effects { import mx.controls.Alert; import mx.effects.IEffectInstance; import mx.events.EffectEvent; import spark.components.mediaClasses.VolumeBar; import spark.effects.Animate; import spark.effects.animation.MotionPath; import spark.effects.animation.SimpleMotionPath; import spark.effects.interpolation.IInterpolator; public class CustomAnimateEffect extends Animate { private var propertys:Vector.<String>=new Vector.<String>(); public function CustomAnimateEffect (target:Object=null) { super(target); motionPaths = new Vector.<MotionPath>(); } public function addMotionPath(property:String,valueFrom:Object,valueTo:Object,interpolator:IInterpolator=null):void{ propertys.push(property); var motionPath:SimpleMotionPath = new SimpleMotionPath(property); motionPath.valueFrom = valueFrom; motionPath.valueTo = valueTo; motionPath.property=property; if(interpolator){ motionPath.interpolator=interpolator; } motionPaths.push(motionPath); } } }
<?xml version="1.0" encoding="utf-8"?> <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600" creationComplete="creationCompleteHandler(event)" xmlns:effects="com.effects.*"> <fx:Script> <![CDATA[ import com.effects.OvalInterpolator; import mx.events.FlexEvent; protected function creationCompleteHandler(event:FlexEvent):void { var ovalInterpolatorx:OvalInterpolator = new OvalInterpolator("x"); ovalInterpolatorx.width=150; ovalInterpolatorx.centerPrintX=300; var ovalInterpolatory:OvalInterpolator = new OvalInterpolator("y"); ovalInterpolatory.height=150; ovalInterpolatory.centerPrintY=300; customAnimateEffect.addMotionPath("x",360,ovalInterpolatorx); customAnimateEffect.addMotionPath("y",ovalInterpolatory); customAnimateEffect.end(); } ]]> </fx:Script> <fx:Declarations> <effects:CustomAnimateEffect duration="1000" id="customAnimateEffect" target="{canv}"/> </fx:Declarations> <mx:Canvas id="canv" x="155" y="37" width="303" height="279" backgroundColor="#632A2A" alpha=".1"/> <s:Button label="Click to fade in the button below" click="customAnimateEffect.play()" /> </s:Application> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |