`
ioryioryzhan
  • 浏览: 153597 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

flex 自定义TweenEffect方法

阅读更多

rh      发现很久没有写BLOG了,罪过罪过,先忙着找工作,工作搞定了,又忙着毕业论文,现在终于有时间来做做Flex了,手生了些,没有项目,完全自娱自乐型。

 

      TweenEffect,补间效果~是一种渐变的类型,像Glow,Move等都是TweenEffect的子类,自已做一个TweenEffect,应该在很多场合用得到。

 

首先选取一个TweenEffect来研究一下,就Glow吧,找到它的原代码,如下(去掉了注释,加上自己的注释 ):

package mx.effects
{

import mx.effects.effectClasses.GlowInstance;
import mx.styles.StyleManager;

public class Glow extends TweenEffect
{
    include "../core/Version.as";
	public function Glow(target:Object = null)
	{
		super(target);
		instanceClass = GlowInstance;
	}
   /*添加一些效果参数,用Inspectable标签声明,这样可以在MXML上设置这些属性*/
	[Inspectable(category="General", defaultValue="NaN")]
	public var alphaFrom:Number;
	[Inspectable(category="General", defaultValue="NaN")]
	public var alphaTo:Number;
	[Inspectable(category="General", defaultValue="NaN")]
	public var blurXFrom:Number;
	[Inspectable(category="General", defaultValue="NaN")]
	public var blurXTo:Number;
	[Inspectable(category="General", defaultValue="NaN")]
	public var blurYFrom:Number;
	[Inspectable(category="General", defaultValue="NaN")]
	public var blurYTo:Number;
	[Inspectable(category="General", format="Color", defaultValue="0xFFFFFFFF")]
	public var color:uint = StyleManager.NOT_A_COLOR;
	[Inspectable(category="General", defaultValue="false")]
	public var inner:Boolean;
	[Inspectable(defaultValue="false")]
	public var knockout:Boolean;
	[Inspectable(category="General", defaultValue="2")]
	public var strength:Number;

	override public function getAffectedProperties():Array /* of String */
	{
		return AFFECTED_PROPERTIES;
	}
	override protected function initInstance(instance:IEffectInstance):void
	{
		super.initInstance(instance);
		//创建效果实例
        var glowInstance:GlowInstance = GlowInstance(instance);
        //将参数传递给实例
		glowInstance.alphaFrom = alphaFrom;
		glowInstance.alphaTo = alphaTo;
		glowInstance.blurXFrom = blurXFrom;
		glowInstance.blurXTo = blurXTo;
		glowInstance.blurYFrom = blurYFrom;
		glowInstance.blurYTo = blurYTo;
		glowInstance.color = color;
		glowInstance.inner = inner;
		glowInstance.knockout = knockout;
		glowInstance.strength = strength;
	}
}

}

 

 真的是so easy,Glow ms就是用来创建实例,外加传递参数的。在设计模式中叫工厂,看来关键还是有GlowInstance类里面,再找到GlowInstance类的代码。

package mx.effects.effectClasses
{
import flash.events.Event;
import flash.filters.GlowFilter;
import mx.core.Application;
import mx.core.mx_internal;
import mx.styles.StyleManager;
public class GlowInstance extends TweenEffectInstance
{
    include "../../core/Version.as";

	public function GlowInstance(target:Object)
	{
		super(target);
	}

	public var alphaFrom:Number;
	public var alphaTo:Number;
	public var blurXFrom:Number;
	public var blurXTo:Number;
	public var blurYFrom:Number;
	public var blurYTo:Number;
	public var color:uint = StyleManager.NOT_A_COLOR;
	public var inner:Boolean;
	public var knockout:Boolean;
	public var strength:Number;

	override public function initEffect(event:Event):void
	{
		super.initEffect(event);
	}

	override public function play():void
	{
		super.play();
		if (isNaN(alphaFrom))
			alphaFrom = 1.0;
		if (isNaN(alphaTo))
			alphaTo = 0;
		if (isNaN(blurXFrom))
			blurXFrom = 5;
		if (isNaN(blurXTo))
			blurXTo = 0;
		if (isNaN(blurYFrom))
			blurYFrom = 5;
		if (isNaN(blurYTo))
			blurYTo = 0;
		if (color == StyleManager.NOT_A_COLOR)
			color = Application.application.getStyle("themeColor");
		if (isNaN(strength))
			strength = 2;
		tween = createTween(
			this, [ color, alphaFrom, blurXFrom, blurYFrom ],
			[ color, alphaTo, blurXTo, blurYTo ], duration);

	}
	override public function onTweenUpdate(value:Object):void
	{
		setGlowFilter(value[0], value[1], value[2], value[3]);
	}
	override public function onTweenEnd(value:Object):void
	{
		setGlowFilter(value[0], value[1], value[2], value[3]);
		super.onTweenEnd(value);	
	}
	
	private function setGlowFilter (color:uint, alpha:Number,
								   blurX:Number, blurY:Number):void
	{
		var filters:Array = target.filters;
		var n:int = filters.length;
		for (var i:int = 0; i < n; i++)
		{
			if (filters[i] is GlowFilter)
				filters.splice(i, 1);
		}
		if (blurX || blurY || alpha)
			filters.push(new GlowFilter(color, alpha, blurX, blurY,
						strength, 1, inner, knockout));
		target.filters = filters;
	}
}

}

 

 

稍微有点复杂了,仔细看看,也还好,开始定义一些参数,就里面参数与Glow中定义是一致的,然后重写了一些关键函数。看看这些函数都干嘛的。

 

play():动画开始播放,首先检查参数,如果没有值,就加上默认值。最后一句是关键,

tween = createTween(
			this, [ color, alphaFrom, blurXFrom, blurYFrom ],
			[ color, alphaTo, blurXTo, blurYTo ], duration);

 

它创建了一个Tween,参数中两个数组很有意思,是一一对应的,一个是From,另一个就是To,这个Tween动画就是这样产生的,数组中的参数,从From淅变到To,中间会停地派发TweenUpdate事件,在类中对这一事件进行处理,实现淅变的效果。

 

TweenUpdate事件便是在onTweenUpdate()函数中得到处理,参数value是From与To之间的中间值,我们根据这个值来做动画,Glow调用的是setGlowFilter()函数来实现。

 

在Tween结束时,即达到To了,就会派发TweenEnd事件,所以也要重写onTweenEnd()函数。

 

好了,都研究完了,ms可以动手写个自己的TweenEffect了,写了个,先看效果,

 

 

<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="300" height="300" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"> <param name="src" value="http://www.mjbox.com/r/io/ioryioryzhan/TestRound.swf"> <embed type="application/x-shockwave-flash" width="300" height="300" src="http://www.mjbox.com/r/io/ioryioryzhan/TestRound.swf"></embed></object>

javaeye变垃圾了吗,连个flash贴进去总是出问题,(http://www.mjbox.com/r/io/ioryioryzhan/TestRound.swf ) 这个是链接

点start按扭,可以看到,一个框框围着控件,一个球球在沿着框框移动,好像不怎么美观,将就一点。它是完成依照Glow编写的,叫Round,Round代码如下:

package effects
{
	import mx.effects.IEffectInstance;
	import mx.effects.TweenEffect;

	public class Round extends TweenEffect
	{
		[Inspectable(category="General", defaultValue="NaN")]
		public var lineColor:uint;
		[Inspectable(category="General", defaultValue="NaN")]
		public var lineWeight:Number;
		[Inspectable(category="General", defaultValue="NaN")]
		public var circleColor:uint;
		[Inspectable(category="General", defaultValue="NaN")]
		public var circleRadio:Number;
		[Inspectable(category="General", defaultValue="NaN")]
		public var distance:Number;
		
		
		public function Round(target:Object=null)
		{
			super(target);
			this.instanceClass = RoundInstance;
		}
		override protected function initInstance(instance:IEffectInstance):void{
			super.initInstance(instance);
			var roundInstance:RoundInstance = RoundInstance(instance);
			roundInstance.lineColor = lineColor;
			roundInstance.lineWeight = lineWeight;
			roundInstance.circleColor = circleColor;
			roundInstance.circleRadio = circleRadio;
			roundInstance.distance = distance;
		}
		
	}
}

 

 不同点在于instanceClass不同了,还有就是参数不同。

没有注释,稍微讲讲这些参数,主要设置线的宽度,颜色,小圆圈的半径,颜色,还有框框与控件的距离。

 

下面是RoundInstance的代码:

package effects
{
	import flash.events.Event;
	
	import mx.core.UIComponent;
	import mx.core.UIComponentGlobals;
	import mx.effects.effectClasses.TweenEffectInstance;
	import mx.core.mx_internal;
	use namespace mx_internal;
	
	public class RoundInstance extends TweenEffectInstance
	{
		public var lineColor:uint;
		public var lineWeight:Number;
		public var circleColor:uint;
		public var circleRadio:Number;
		public var distance:Number;
		
		public function RoundInstance(target:Object)
		{
			super(target);
		}
		override public function initEffect(event:Event):void{
			super.initEffect(event);
			
		}
		override public function play():void{
			if (isNaN(lineColor))
				lineColor = 0xff0000;
			if (isNaN(circleColor))
				circleColor = 0xff0000;
			if (isNaN(distance))
				distance = 3;
			if (isNaN(lineWeight))
				lineWeight = 1;
			if (isNaN(circleRadio))
				circleRadio = 3;
			//保证参数合理性
			if(distance<=0){
				distance = 3;
			}	
			if(lineWeight > 2 * distance){
				lineWeight = 2 * distance;
			}
			if(circleRadio > distance){
				circleRadio = distance;
			}
			
			var targetUI:UIComponent = target as UIComponent;
			var w:Number = targetUI.width;
			var h:Number = targetUI.height;
			//创建Tween
			tween = createTween(this,[0],[2*(w+2*distance)+2*(h+2*distance)],duration);
		}
		override public function onTweenUpdate(value:Object):void{
			draw(value[0]);
		}
		override public function onTweenEnd(value:Object):void{
			var targetUI:UIComponent = target as UIComponent;
			targetUI.graphics.clear();
                        super.onTweenEnd(value);
		}
		
		private function draw(d:Number):void{
			var targetUI:UIComponent = target as UIComponent;
			targetUI.graphics.clear();
			
			targetUI.graphics.lineStyle(lineWeight,lineColor);
			targetUI.graphics.moveTo(-distance,-distance);
			targetUI.graphics.lineTo(-distance,targetUI.height+distance);
			targetUI.graphics.lineTo(targetUI.width + distance,targetUI.height+distance);
			targetUI.graphics.lineTo(targetUI.width + distance,-distance);
			
			var x:Number;
			var y:Number;
			var h:Number = targetUI.height + 2*distance;
			var w:Number = targetUI.width  + 2*distance;
			if(d<h){
				x = -distance;
				y = d;
			}else if(d>=h&&d<(w+h)){
				x = d - h;
				y = h - distance;
			}else if(d>=(w+h)&&d<(w+2*h)){
				x = w - distance;
				y = w + 2* h - d;
			}else{
				x = 2*w + 2* h - d;
				y = - distance;
			}
			
			targetUI.graphics.beginFill(circleColor);
			targetUI.graphics.drawCircle(x,y,circleRadio);
			targetUI.graphics.endFill();
		}
	}
}

 

看看Tween的创建

tween = createTween(this,[0],[2*(w+2*distance)+2*(h+2*distance)],duration);

从0开始,一直到2*(w+2*distance)+2*(h+2*distance),进行淅变,这个长表达式就是框框的周长,

 

draw函数,便是以中间值,计算当前球球的位置,进行绘制。

 

主程序,很简单,三个按扭,

 

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
 creationComplete="init()" backgroundColor="0xffffff" 
 xmlns:myeffect="effects.*" width="300" height="300">
	<mx:Script>
		<![CDATA[
			import mx.effects.Effect;
			import mx.events.EffectEvent;
			import mx.effects.Glow;
			import effects.Round;
			internal function init():void{
				
			}
			internal function onClickBtn2(e:MouseEvent):void{
				round1.play();
			}
			internal function onClickBtn3(e:MouseEvent):void{
				round1.end();
			}
		]]>
	</mx:Script>
	<myeffect:Round id="round1" target="{btn}" lineColor="0xff0000" lineWeight="1" 
		circleColor="0x0000ff" circleRadio="3" distance="10" duration="2000"/>
	<mx:Button x="50" y="50" width="90" height="50" id="btn"  label="Button"/>
	<mx:Button x="50" y="200" width="90" height="50" id="btn2" label="start"click="onClickBtn2(event)"/>
	<mx:Button x="150" y="200" width="90" height="50" id="btn3" label="end" click="onClickBtn3(event)"/>
</mx:Application>

 

 

点击调试,ft,出问题了,框框也有,球也有,也转的挺好,就是转完后不消失,我记得在onTweenEnd()中已经将画布clear()了,看来是super.onTweenEnd();有问题,点进去看看,果然是它,

/*in Class TweenEffectInstance*/

public function onTweenEnd(value:Object):void 
	{
		onTweenUpdate(value);
		tween = null;
		if (mx_internal::needToLayout)
			UIComponentGlobals.layoutManager.validateNow();

		finishRepeat();
	}

 

它在里面最后还是调用了一次onTweenUpdate(),所以又将框框球球画了上去,会消失才怪,只好,将下面四行代码移到RoundInstance类的onTweenUpdate()里去,修改代码:

 

/*in Class RoundInstance*/

override public function onTweenEnd(value:Object):void{
	var targetUI:UIComponent = target as UIComponent;
	targetUI.graphics.clear();
	    //下面四行代码,是从父类中移过来的
	tween = null;
	if (mx_internal::needToLayout)
		UIComponentGlobals.layoutManager.validateNow();
	finishRepeat();

}

 

现在开以了,点击运行,就是上面flash所展示的程序了。

 

欢迎批评指教~~

 

另外求教:

RepeatCount是如何发挥作用的,相关代码在哪 ?

分享到:
评论
2 楼 yuanyang0710 2009-10-16  
不错,牛!
1 楼 yhustc 2009-08-16  

友情链接一下
关于自定义effect的实现,我引用了你的链接。我的文章里分析了repeatCount相关的内容 
http://www.yhustc.com/flex_effect_repeatCount.html

相关推荐

Global site tag (gtag.js) - Google Analytics