2009-05-19 6 views
1

Je suis en train d'animer un rectangle rond dans ActionScript 3.Animer un rectangle rond dans ActionScript 3

Je veux qu'il apparaisse dans le centre de l'écran, puis se développer rapidement dans les quatre directions. La taille initiale devrait être d'environ 30x10 pixels et la taille finale d'environ 300x100 pixels. L'animation devrait prendre entre 500 et 1000 millisecondes. Je voudrais que la boîte dépasse légèrement ces dimensions dans les dernières images, puis rebondisse à la bonne taille. J'utilise maintenant un tween Back easeOut et un scale9Grid, grâce à la suggestion de TypeOneError, mais je ne suis pas encore sorti de l'ornière. Je peux obtenir la boîte pour rebondir à droite et à gauche, et l'animation semble correcte, sauf que je voudrais que la boîte reste centrée. La fonction ScaleFromCenterConstant est presque correcte, car la boîte reste centrée, mais si j'envoie l'échelle calculée par l'interpolation, la boîte explose de l'écran.

Devrais-je utiliser Matrix.scale() ou dois-je définir Matrix.a .d .tx et .ty individuellement?

Voici mon code jusqu'ici:

package { 

import fl.transitions.Tween; 
import fl.transitions.TweenEvent; 
import fl.transitions.easing.*; 

import flash.display.*; 
import flash.geom.Matrix; 
import flash.geom.Point; 
import flash.geom.Rectangle; 
import flash.text.TextField; 
import flash.text.TextFieldAutoSize; 
import flash.utils.setTimeout; 

public class Scaling extends Sprite 
{ 

    private var startWidth:int = 50; 
    private var startHeight:int = 30; 
    private var startLineWidth:int = 5; 
    private var startEllipse:int = 15; 
    private var startCenter:Point = new Point(400, 300); 

    public var mySprite:Sprite = new Sprite(); 
    public var myTween:Tween; 

    public function Scaling() { 
     this.stage.scaleMode = StageScaleMode.NO_SCALE; 
     this.stage.align = StageAlign.TOP_LEFT; 

     graphics.beginFill(0x000000); 
     graphics.drawRect(0, 0, 800, 600); 
     mySprite.graphics.endFill(); 

     mySprite.graphics.beginFill(0xF7F3DC); 
     mySprite.graphics.lineStyle(startLineWidth, 0xD35F72); 
     mySprite.graphics.drawRoundRect(0, 0, startWidth, startHeight, startEllipse, startEllipse); 
     mySprite.graphics.endFill(); 

     mySprite.x = startCenter.x - startWidth/2; 
     mySprite.y = startCenter.y - startHeight/2; 
     mySprite.width = startWidth; 
     mySprite.height = startHeight; 

     mySprite.scale9Grid = new Rectangle(10, 10, 30, 10); 

     setTimeout(GoGoGadgetScaling, 1000); 
    } 

    private function GoGoGadgetScaling():void { 
     addChild(mySprite); 

     var o:Object = new Object(); 
     o["scale"] = 1; 

     myTween = new Tween(o, "scale", Back.easeOut, 1, 5, 0.3, true); 

     myTween.addEventListener(TweenEvent.MOTION_CHANGE, function(evt:TweenEvent):void { 
      //ScaleRightAndDown(mySprite, o["scale"] * 2, o["scale"], startCenter); 
      //ScaleFromCenterConstant(mySprite, 1.2, 1.1, startCenter); 
      ScaleFromCenter(mySprite, o["scale"], o["scale"], startCenter); 
     }); 

     myTween.addEventListener(TweenEvent.MOTION_FINISH, function(evt:TweenEvent):void { 
      setTimeout(function():void { 
       var tf:TextField = new TextField(); 
       tf.autoSize = TextFieldAutoSize.LEFT; 
       tf.text = "Finished..."; 
       mySprite.addChild(tf); 
      }, 100); 
     }); 
    } 

    private function ScaleRightAndDown(ob:*, sx:Number, sy:Number, ptScalePoint:Point):void { 
     var m:Matrix = ob.transform.matrix; 
     m.a = sx; 
     m.d = sy; 
     mySprite.transform.matrix = m; 
    } 

    private function ScaleFromCenterConstant(ob:*, sx:Number, sy:Number, ptScalePoint:Point):void { 
     var m:Matrix = ob.transform.matrix; 
     m.ty -= ptScalePoint.y; 
     m.tx -= ptScalePoint.x; 
     m.scale(sx, sy); 
     m.tx += ptScalePoint.x; 
     m.ty += ptScalePoint.y; 
     ob.transform.matrix = m; 
    } 

    // This does not work 
    private function ScaleFromCenter(ob:*, sx:Number, sy:Number, ptScalePoint:Point):void { 
     var m:Matrix = ob.transform.matrix; 
     m.ty -= ptScalePoint.y; 
     m.tx -= ptScalePoint.x; 
     m.scale(sx, sy); 
     m.a = sx; 
     m.d = sy; 
     m.tx += ptScalePoint.x; 
     m.ty += ptScalePoint.y; 
     ob.transform.matrix = m; 
    } 

} 
} 

MISE À JOUR:

Yay, grâce à Niko Nyman, je l'ai eu à travailler. Voici le code final pour les personnes intéressées:

package { 

import fl.transitions.Tween; 
import fl.transitions.TweenEvent; 
import fl.transitions.easing.*; 
import flash.display.*; 
import flash.geom.Point; 
import flash.geom.Rectangle; 
import flash.text.*; 
import flash.utils.setTimeout; 

public class Scaling extends Sprite 
{ 

    private var startWidth:int = 400; 
    private var startHeight:int = 150; 
    private var startLineWidth:int = 5; 
    private var startEllipse:int = 15; 
    private var startCenter:Point = new Point(400, 300); 

    public var mySprite:Sprite = new Sprite(); 
    public var myTween:Tween; 

    public function Scaling() { 
     this.stage.scaleMode = StageScaleMode.NO_SCALE; 
     this.stage.align = StageAlign.TOP_LEFT; 

     mySprite.graphics.beginFill(0xF7F3DC); 
     mySprite.graphics.lineStyle(startLineWidth, 0xD35F72); 
     mySprite.graphics.drawRoundRect(-startWidth/2, -startHeight/2, startWidth, startHeight, startEllipse, startEllipse); 
     mySprite.graphics.endFill(); 

     mySprite.x = startCenter.x; 
     mySprite.y = startCenter.y; 

     mySprite.scale9Grid = new Rectangle(-startWidth/2 + startEllipse/2, -startHeight/2 + startEllipse/2, startWidth - startEllipse, startHeight - startEllipse); 

     mySprite.scaleX = 0; 
     mySprite.scaleY = 0; 

     addChild(mySprite); 

     setTimeout(GoGoGadgetScaling, 1000); 
    } 

    private function GoGoGadgetScaling():void { 

     var o:Object = new Object(); 
     o["scale"] = 1; 

     myTween = new Tween(o, "scale", Back.easeOut, 0.1, 1, 0.5, true); 

     myTween.addEventListener(TweenEvent.MOTION_CHANGE, function(evt:TweenEvent):void { 
      mySprite.scaleX = o["scale"]; 
      mySprite.scaleY = o["scale"]; 
     }); 

     myTween.addEventListener(TweenEvent.MOTION_FINISH, function(evt:TweenEvent):void { 
      setTimeout(function():void { 
       var tf:TextField = new TextField(); 
       tf.autoSize = TextFieldAutoSize.LEFT; 
       tf.text = "Finished..."; 
       mySprite.addChild(tf); 
      }, 100); 
     }); 
    } 

} 
} 
+0

Essayez d'utiliser Elastic.easeOut. –

Répondre

0

Pourriez-vous dessiner seulement les graphiques centrés (ie. Mettre le coin supérieur gauche à x = -startWidth/2 et y = -startHeight/2 au lieu de 0, 0), puis faire un simple tween d'échelle sur mySprite? De cette façon, vous pouvez vous débarrasser de tous les calculs de la matrice ...

+0

Brillant, merci! –

0

Avez-vous essayé d'utiliser easeOut?

myTween = new Tween(o, "scale", Elastic.easeOut, 1, 1.5, 0.75, true); 
0

Si vous cherchez à « trop grand » et revenir, vous voulez la transition Back.easeOut. Puis-je également vous suggérer d'utiliser l'outil Flash Authoring pour accélérer la création des graphiques? Vous pouvez utiliser l'outil Rectangle Primitive pour créer un rectangle arrondi, le convertir en MovieClip ou Sprite et sélectionner l'échelle à 9 tranches. Si vous ajustez les tranches pour qu'elles commencent et se terminent à l'endroit où la courbe commence, elle ne fera que mettre à l'échelle le centre et les coins resteront arrondis.

+0

La transition Back.easeOut était ce dont j'avais besoin, aussi j'ai mis le scale9Grid au travail avec de bons résultats, merci! Malheureusement, j'ai encore un peu de difficulté avec la mise à l'échelle, j'ai mis à jour la question en conséquence. –

+0

On dirait que vous allez de 1 à 5, ce qui serait 500% plus grand. Peut-être que ça sort de l'écran. Assez grosse augmentation. – typeoneerror

+0

Eh bien, je commence avec une largeur de 50px, donc une augmentation de 500% entraînerait une largeur finale de 250px, si mes maths sont bons. Le problème avec l'appel de Matrix.scale() est que chaque appel suivant est exponentiel. –