續前篇。
如果每一次 apply pixel bender 到轉場 effect 都要寫一長串的話實在有點堅強過頭... 要符合懶人精神將常用的 pixel bender filter 效果實作成 TweenEffect 才是明智的選擇。參考了 Flex help 與其他 TweenEffects,以下是簡單客製 TweenEffect 並加上 pixel bender filter 的作法:
每一組 TweenEffect 都由兩個 class 組成: TweenEffectInstance 與 TweenEffect ; 各自有幾個重點 functuon 需要被 override。別忘了先將上篇提到的 CrystallizeShader.as 放到 effects/ 下。
1. 製作 effects/CrystalEffectInstance.as:( 顧名思義就是被作用的實體 )
package effects
{
import flash.display.Shader;
import flash.filters.ShaderFilter;
import mx.effects.Tween;
import mx.effects.effectClasses.TweenEffectInstance;
public class CrystalEffectInstance extends TweenEffectInstance
{
public var sizeTo:Number;
public var sizeFrom:Number;
private var shader:CrystallizeShader = CrystallizeShader.getInstance();
public function CrystalEffectInstance(target:Object)
{
super(target);
}
// Override play() method class.
override public function play():void {
// 一定要有 super.play().
super.play();
sizeFrom = isNaN(sizeFrom) ? 50 : sizeFrom;
sizeTo = isNaN(sizeTo) ? 0 : sizeTo;
var tween:Tween = createTween(this, sizeFrom, sizeTo, duration);
}
// Override onTweenUpdate() method.
override public function onTweenUpdate(val:Object):void {
shader.size = Number(val);
applyFilter();
}
// Override onTweenEnd() method.
override public function onTweenEnd(val:Object):void
{
applyFilter();
super.onTweenEnd(val);
}
private function applyFilter():void{
var filters:Array = target.filters;
for (var i:int = filters.length; i-->0;)
{
if (filters[i] is ShaderFilter)
filters.splice(i, 1);
}
if(shader.size)
filters.push( new ShaderFilter( shader ) );
target.filters = filters;
}
}
}
主要 override play(), onTweenEnd(), onTweenUpdate(),並加上一個 applyFilter 保障其他附加在實體上的 filters 不會被刪掉...=P
2. effects/CrystalEffect.as
package effects
{
import mx.effects.TweenEffect;
import mx.effects.IEffectInstance;
public class CrystalEffect extends TweenEffect
{
public var sizeTo:Number;
public var sizeFrom:Number;
public function CrystalEffect(targetObj:* = null) {
super(targetObj);
instanceClass= CrystalEffectInstance;
}
//override getAffectedProperties()
override public function getAffectedProperties():Array
{
return [ "filters" ];
}
// Override initInstance() method.
override protected function initInstance(inst:IEffectInstance):void {
super.initInstance(inst);
CrystalEffectInstance(inst).sizeFrom = sizeFrom;
CrystalEffectInstance(inst).sizeTo = sizeTo;
}
}
}
繼承 TweenEffect 的寫法有點固定,改寫 initInstance() and getAffectedProperties()
測試:main.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:effect = "effects.*"
layout="horizontal" >
<effect:CrystalEffect sizeFrom="200" duration="500" id="crystal" />
<effect:CrystalEffect sizeFrom="500" sizeTo="10" duration="800" id="crystal1" />
<mx:Panel width="250" height="200" title="Pixel Bender Test"
backgroundColor="#F8F8F8" creationCompleteEffect="crystal" />
<mx:Panel width="250" height="200" title="Pixel Bender Test"
backgroundColor="#F8F8F8" creationCompleteEffect="crystal1" />
</mx:Application>
Comments
Post a Comment