Ho creato un po' di tempo fa, partendo da una classe di and80, un classe che maschera e smaschera un clip con le proprietà scale della maschera.
Ieri c'ho rimesso mano aggiungendo la possibilità di rilanciare la classe sullo stesso target, anche se la tween non è finita.
Forse non è elegante nel codice, magari potete dargli una sistemata, per il resto mi pare piuttosto affidabile. Un problema che non ho risolto è che se il clip da mascherare non è a 0,0. La maschera non si posizione sopra, ma su 0,0.
Ho anche tradotto in AS3.
Ah, io faccio uso di TweenLite (greensock.com), se usate un'altra piattaforma di Tween dovete arrangiarvi :)
(Di recente ho scoperto la classe TransitionManager, che fa la stessa cosa, ma se rilanciate un'altra tween a metà animazione riparte dagli estremi)
Il costruttore è
new MascheraSlide(target:MovieClip/Display, verso:String, inOut:String, easeType:Function, duration:Number, delay:Number) {
il verso può essere "left/top/right/bottom"
inOut è "in" o "out"
Utilizzocodice:import mx.transitions.easing.Regular; import gs.TweenLite; class MascheraSlide { private var __target:MovieClip; private var __verso:String; private var __width:Number; private var __height:Number; private var __time:Number; private var __easeType:Function; private var __intv:Number; private var __inOut:String; private var __delay:Number; private var objTween:Object; private var xscale:Number; private var yscale:Number; private var x:Number; private var y:Number; public var onMotionFinished:Function; function MascheraSlide(target:MovieClip, verso:String, inOut:String, easeType:Function, duration:Number, delay:Number) { var path = this; if (target != undefined) { __target = target; // inizializzo le variabili lasciate undefined if (verso==undefined){__verso = "left";}else{__verso = verso;} if (inOut==undefined){__inOut="in";}else{__inOut=inOut;} if (easeType==undefined){__easeType=Regular.easeOut;}else{__easeType = easeType;} if (duration==undefined){__time = 1;}else{__time = duration;} if (delay==undefined){__delay=0;}else{__delay=delay;} //primi parametri oggetto tween objTween = new Object(); objTween.onComplete = chiudi; objTween.ease = __easeType; objTween.onCompleteParams = [__target, __inOut, path]; objTween.delay = __delay; //posizione finale della maschera in base al verso, se in verso, l'origine del target, se out, verso gli estremi // scale finale if (__inOut=="in"){ x = target._x y = target._y xscale=100; yscale=100; }else{ x = target._width+target._x y = target._height+target._y xscale=0; yscale=0; } switch (__verso){ default: case "left": objTween._xscale=xscale; break; case "top": objTween._yscale=yscale; break; case "right": objTween._xscale=xscale; objTween._x = x; break; case "bottom": objTween._yscale=yscale; objTween._y = y; break; } //se la maschera già esiste (perchè ho già lanciato la classe su questo target e deve finire la tween) if (target._parent["cmask_"+target._name]!=undefined){ //eseguo la nuova tween animateMask(__target, __time) }else{ //altrimenti disegno la maschera drawMask(__target, __verso, __easeType, __time, __delay, __inOut) } }else{ endOff(__target, __inOut); } } //disegna un rettangolo private function drawSquare(target:MovieClip, name:String, level:Number, wdt:Number, hgt:Number):MovieClip { var rt:MovieClip=target.createEmptyMovieClip(name, level); rt.lineStyle(0, 0, 0); rt.moveTo(0, 0); rt.beginFill(0xCC0000,0); rt.lineTo(wdt, 0); rt.lineTo(wdt, hgt); rt.lineTo(0, hgt); rt.lineTo(0, 0); rt.endFill(); return rt; } private function drawMask(target:MovieClip, verso:String, easeType:Function, duration:Number, delay:Number, inOut:String) { var mk:MovieClip=drawSquare(target._parent, "cmask_"+target._name, target._parent.getNextHighestDepth(), target._width, target._height); mk._x = target._x; mk._y = target._y; target.setMask(mk); if (inOut=="in"){ switch (verso){ default: case "left": mk._xscale=0; break; case "top": mk._yscale=0; break; case "right": mk._xscale=0; mk._x = target._width+target._x; break; case "bottom": mk._yscale=0; mk._y = target._height+target._y; break; } } animateMask(target, duration, "to") } private function animateMask(trg, dur){ trg._visible=true; TweenLite.to(trg._parent["cmask_"+trg._name], dur, objTween); } private function endOff(target:MovieClip, inOut:String) { target.setMask(null); if (inOut!="in"){ target._visible=false; } if (target._parent["cmask_"+target._name]!=undefined){ target._parent["cmask_"+target._name].removeMovieClip(); } this['onMotionFinished'](); } public function getMask():MovieClip{ return __target._parent["cmask_"+__target._name]; } private function chiudi(target, inOut, path){ path['endOff'](target, inOut); } }
codice:import gs.TweenLite import mx.transitions.easing.* verso = "bottom" var MS =new MascheraSlide(pippo, verso, "in", Strong.easeOut, 2) MS.onMotionionFinished=function(){ trace("1") } /* decommentare per vedere lanciare altre tween function chiudi(){ var cc = new MascheraSlide(pippo, verso, "out", Strong.easeOut, 2) cc.onMotionFinished=function(){ trace("2") } } function apri(){ dd = new MascheraSlide(pippo, verso, "in", Strong.easeOut, 2) dd.onMotionFinished=function(){ trace("2") } } TweenLite.delayedCall(.5, chiudi) TweenLite.delayedCall(1, apri) */
****************
Versione AS3
USOcodice:package { import flash.display.*; import flash.events.Event; import flash.events.EventDispatcher; import gs.TweenLite; import fl.transitions.easing.*; public class MascheraSlide extends EventDispatcher{ private var __target:DisplayObjectContainer; private var __verso:String; private var __time:Number; private var __easeType:Function; private var __intv:Number; private var __inOut:String; private var __delay:Number; private var __toFrom:String; private var objTween:Object; private var __xscale:Number; private var __yscale:Number; private var __x:Number; private var __y:Number; private var box:MovieClip; function MascheraSlide(target:DisplayObjectContainer=null, verso:String ="left", inOut:String="in", easeType:Function = null, duration:Number=.5, delay:Number=0) { __inOut=inOut; __target = target; __verso = verso; __easeType = easeType; __time = duration; __delay=delay; drawMask(__target, __verso, __inOut, __easeType, __time, __delay); } private function drawMask(target:DisplayObjectContainer, verso:String,inOut:String, easeType:Function, duration:Number, delay:Number) { if (target is DisplayObjectContainer){ //primi parametri oggetto tween objTween = new Object(); objTween.onComplete = endOff; objTween.ease = easeType; objTween.onCompleteParams = [target, inOut]; objTween.delay = delay; //posizione finale della maschera in base al verso, se "in", verso l'origine del target, se out, verso gli estremi //posizione dello scale finale scale finale if (inOut=="in"){ __x = target.x __y = target.y __xscale=1; __yscale=1; }else{ __x = target.width+target.x __y = target.height+target.y __xscale=0; __yscale=0; } switch (__verso){ default: case "left": objTween.scaleX=__xscale; break; case "top": objTween.scaleY=__yscale; break; case "right": objTween.scaleX=__xscale; objTween.x = __x; break; case "bottom": objTween.scaleY=__yscale; objTween.y = __y; break; } var box:MovieClip; if (target["__refMS"]==undefined){ box = new MovieClip(); box.graphics.beginFill(0,.5) box.graphics.drawRect(0,0, target.width, target.height); box.graphics.endFill(); target.parent.addChild(box); target["__refMS"] = box; box.x=target.x box.y=target.y if (inOut=="in"){ switch (verso){ default: case "left": box.scaleX=0; break; case "top": box.scaleY=0; break; case "right": box.scaleX=0; box.x = target.width+target.x; break; case "bottom": box.scaleY=0; box.y = target.height+target.y; break; } } target.mask = box; }else{ box = target["__refMS"] } target.visible=true; TweenLite.to(box, duration, objTween); }else{ endOff(__target, __inOut) } } private function endOff(target:DisplayObjectContainer, inOut:String) { target.mask = null; target.parent.removeChild(target["__refMS"]) target["__refMS"] = undefined; if (inOut!="in"){ target.visible = false; } dispatchEvent(new Event("COMPLETED")); } } }
codice:import gs.* import fl.transitions.easing.* var verso:String = "left" var pp =new MascheraSlide(pippo, verso, "in", None.easeNone, 1) function fatto(e:Event){ trace("!") } pp.addEventListener("COMPLETED", fatto) function chiudi(){ var cc = new MascheraSlide(pippo, "top", "out", Strong.easeOut, 5) } function apri(){ var dd = new MascheraSlide(pippo, verso, "in", Strong.easeOut, 5) } TweenLite.delayedCall(.5, chiudi) TweenLite.delayedCall(2, apri)

Rispondi quotando