Animating a round rectangle in ActionScript 3

I am trying to animate a round rectangle in ActionScript 3.

I want it to appear in the center of the screen and then quickly unfold in all four directions. The original size should be around 30x10 pixels and the final size around 300x100 pixels. The animation should take between 500 and 1000 milliseconds. I would like the box to grow a little over these dimensions in the last few frames, and then return to the correct size.

I am now using Back easeOut and scale9Grid animations thanks to the TypeOneError suggestion, however I'm still not out of the woods. I can get the box to bounce right and down and the animation looks correct, except that I want the box to stay centered. The ScaleFromCenterConstant function is almost correct as the box stays centered, however if I send along the scale calculated with the tween the box explodes off the screen.

Should I use Matrix.scale () or do I need to install Matrix.adtx and .ty separately?

Here's my code:

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;
    }

}   
}

      

UPDATE:

Thanks to Nico Niemann, I got the job. Here is the final code for the few interested:

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);
        });
    }

}   
}

      

+1


a source to share


3 answers


Could you just draw the graphic to the center (i.e. put the top left corner in x = -startWidth/2

and y = -startHeight/2

instead of 0, 0

) and then do a simple scale animation on mySprite? This way you can get rid of all matrix calculations ...



0


a source


Have you tried using easeOut?



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

      

0


a source


If you want to "outgrow" and come back, you need a transition Back.easeOut

. May I also assume that you are using Flash Authoring to speed up your graphics creation? You can use the Rectangle Primitive tool to create a rounded rectangle, convert it to MovieClip or Sprite, and select 9-slice scaling. If you adjust the slices so that they start and end where the curve begins, it will only scale the center and the corners will remain round.

0


a source







All Articles