Tutorial :Animate a round rectangle in ActionScript 3



Question:

I'm trying to animate a round rectangle in ActionScript 3.

I want it to appear in the centre of the screen, and then grow out quickly in all four directions. Initial size should be about 30x10 pixels and final size about 300x100 pixels. The animation should take somewhere between 500 and 1000 milliseconds. I'd like the box to slightly outgrow these dimensions in the last few frames and then bounce back to the right size.

I'm now using a Back easeOut tween and a scale9Grid, thanks to TypeOneError's suggestion, however I'm still not out of the woods. I can get the box to bounce out right and downwards, and the animation looks right, except I would like the box to remain centered. The function ScaleFromCenterConstant is almost right, as the box remains centered, however if I send through the scale calculated by the tween the box explodes off the screen.

Should I be using Matrix.scale() or should I be setting Matrix.a .d .tx and .ty individually?

Here's my code thus far :

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 :

Yay, thanks to Niko Nyman, I got it working. Here is the final code for the interested few :

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


Solution:1

Could you just draw the graphics centered (ie. put the top-left corner at x = -startWidth/2 and y = -startHeight/2 instead of 0, 0), then do a simple tween of scale on mySprite? This way you could get rid of all the matrix calculations...


Solution:2

Have you tried to use easeOut?

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


Solution:3

If you're looking to "outgrow" and come back, you want the Back.easeOut transition. Might I also suggest that you use the Flash Authoring tool to speed up the creation of the graphics as well? You could use the Rectangle Primitive tool to create a rounded rectangle, convert it to a MovieClip or Sprite and select 9-slice-scaling. If you adjust the slices so they start and end where the curve starts, it will only scale the center up and the corners will stay round.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »