AS3: DistortionTweener
View Example 1
View Example 2
View Example 3
View Documentation
Download Class & Example Files
The DistortionTweener allows you to distort four points of an object. It is an easy to way make distortions such as trapezoids on a movie clip.
The DistortionTweener uses Ruben Swieringa's DistortImage class and is based on a sample .FLA provided by Tam Ho on how to use DistortImage in Flash.
-
/**
-
* The DistortionTweener allows you to distort four points of an object. It is an easy to way make distortions such as trapezoids on a movie clip.
-
*
-
* The DistortionTweener uses Ruben Swieringa's DistortImage class (http://www.rubenswieringa.com/blog/distortimage) and is based on a sample .FLA provided by Tam Ho (http://www.flashteam.com.au) on how to use DistortImage in Flash.
-
*
-
* @usage
-
* <code>
-
* <pre>
-
import com.reintroducing.transitions.DistortionTweener;
-
import fl.transitions.easing.Regular;
-
var dt:DistortionTweener = new DistortionTweener(s, clip_mc, tl, tr, br, bl, 5);
-
dt.addEventListener(Event.INIT, onDistortStarted);
-
dt.addEventListener(Event.COMPLETE, onDistortFinished);
-
dt.tweenTo(new Point(-50, -50), new Point(410, -50), new Point(310, 266), new Point(50, 266), Regular.easeIn, .5);
-
// fired off when the distortion tween starts
-
function onDistortStarted($evt:Event):void
-
{
-
trace("Starting the distortion.");
-
}
-
// fired off whent he distortion tween ends
-
function onDistortFinished($evt:Event):void
-
{
-
trace("Finished the distortion.");
-
}
-
* </pre>
-
* </code>
-
*
-
* @author Matt Przybylski [http://www.reintroducing.com]
-
* @version 1.0
-
*/
-
-
package com.reintroducing.transitions
-
{
-
import flash.display.Bitmap;
-
import flash.display.BitmapData;
-
import flash.display.MovieClip;
-
import flash.display.Shape;
-
import flash.events.Event;
-
import flash.events.EventDispatcher;
-
import flash.geom.Point;
-
-
import org.flashsandy.display.DistortImage;
-
-
import fl.transitions.Tween;
-
import fl.transitions.TweenEvent;
-
-
public class DistortionTweener extends EventDispatcher
-
{
-
//- PRIVATE & PROTECTED VARIABLES -------------------------------------------------------------------------
-
-
private var _holder:*;
-
private var _mc:MovieClip;
-
private var _mcWidth:Number;
-
private var _mcHeight:Number;
-
private var _bmd:BitmapData;
-
private var _bmp:Bitmap;
-
private var _container:Shape;
-
private var _tl:Point;
-
private var _tr:Point;
-
private var _br:Point;
-
private var _bl:Point;
-
private var _distortion:DistortImage;
-
private var _tweenFunc:Function;
-
private var _tweenTime:Number;
-
private var _precision:uint;
-
-
// tweens
-
private var _tlXTween:Tween;
-
private var _tlYTween:Tween;
-
private var _trXTween:Tween;
-
private var _trYTween:Tween;
-
private var _brXTween:Tween;
-
private var _brYTween:Tween;
-
private var _blXTween:Tween;
-
private var _blYTween:Tween;
-
-
//- PUBLIC & INTERNAL VARIABLES ---------------------------------------------------------------------------
-
-
public static const DEFAULT_NAME:String = "com.reintroducing.transitions.DistortionTweener";
-
-
//- CONSTRUCTOR -------------------------------------------------------------------------------------------
-
-
/**
-
* Creates a new instance of the DistortionTweener class. The point values are relative to the holder clip, NOT the stage.
-
*
-
* @usage <pre><code>var dt:DistortionTweener = new DistortionTweener($holder, $mc, $tl, $tr, $br, $bl, $precision);</code></pre>
-
*
-
* @param $holder The DisplayObject that will be used to hold your distorted bitmap
-
* @param $mc The source movie clip that will be used to copy into the bitmap that will be distorted
-
* @param $tl The top left point to use in the distortion
-
* @param $tr The top right point to use in the distortion
-
* @param $br The bottom right point to use in the distortion
-
* @param $bl The bottom left point to use in the distortion
-
* @param $precision A uint representing the value to use as the precision in the DistortImage class
-
*/
-
-
public function DistortionTweener($holder:*, $mc:MovieClip, $tl:Point, $tr:Point, $br:Point, $bl:Point, $precision:uint):void
-
{
-
this._holder = $holder;
-
this._mc = $mc;
-
this._mcWidth = this._mc.width;
-
this._mcHeight = this._mc.height;
-
this._tl = $tl;
-
this._tr = $tr;
-
this._br = $br;
-
this._bl = $bl;
-
this._precision = $precision;
-
-
this.init();
-
}
-
-
//- PRIVATE & PROTECTED METHODS ---------------------------------------------------------------------------
-
-
private function init():void
-
{
-
this._mc.visible = false;
-
-
this._bmd = new BitmapData(this._mcWidth, this._mcHeight, true, 0x00FFFFFF);
-
this._bmd.draw(this._mc);
-
-
this._bmp = new Bitmap(this._bmd);
-
this._container = new Shape();
-
-
this._holder.addChild(this._container);
-
-
this._distortion = new DistortImage(this._mcWidth, this._mcHeight, this._precision, this._precision);
-
this._distortion.setTransform(this._container.graphics, this._bmp.bitmapData, this._tl, this._tr, this._br, this._bl);
-
}
-
-
//- PUBLIC & INTERNAL METHODS -----------------------------------------------------------------------------
-
-
/**
-
* Tweens the distortion. As with the constructor, the point values are relative to the holder clip, NOT the stage.
-
*
-
* <p>
-
* The tweenTo method dispatches two events:
-
* <ul>
-
* <li>Event.INIT: Dispatched when the tweening begins</li>
-
* <li>Event.COMPLETE: Dispatched when the tweening ends</li>
-
* </ul>
-
* </p>
-
*
-
* @usage <pre><code>dt.tweenTo(new Point(-50, -50), new Point(410, -50), new Point(310, 266), new Point(50, 266), Regular.easeIn, .5);</code></pre>
-
*
-
* @param $tl The top left point to end the tween at
-
* @param $tr The top right point to end the tween at
-
* @param $br The bottom right point to end the tween at
-
* @param $bl The bottom left point to end the tween at
-
* @param $tweenFunc The easing function to use in the tween
-
* @param $time The duration, in seconds, of the tween
-
*
-
* @return Nothing
-
*/
-
-
public function tweenTo($tl:Point, $tr:Point, $br:Point, $bl:Point, $tweenFunc:Function, $time:Number):void
-
{
-
this.dispatchEvent(new Event(Event.INIT));
-
-
this._tweenFunc = $tweenFunc;
-
this._tweenTime = $time;
-
-
// top left tweens
-
this._tlXTween = new Tween(this._tl, "x", this._tweenFunc, this._tl.x, $tl.x, this._tweenTime, true);
-
this._tlYTween = new Tween(this._tl, "y", this._tweenFunc, this._tl.y, $tl.y, this._tweenTime, true);
-
-
// top right tweens
-
this._trXTween = new Tween(this._tr, "x", this._tweenFunc, this._tr.x, $tr.x, this._tweenTime, true);
-
this._trYTween = new Tween(this._tr, "y", this._tweenFunc, this._tr.y, $tr.y, this._tweenTime, true);
-
-
// bottom right tweens
-
this._brXTween = new Tween(this._br, "x", this._tweenFunc, this._br.x, $br.x, this._tweenTime, true);
-
this._brYTween = new Tween(this._br, "y", this._tweenFunc, this._br.y, $br.y, this._tweenTime, true);
-
-
// bottom left tweens
-
this._blXTween = new Tween(this._bl, "x", this._tweenFunc, this._bl.x, $bl.x, this._tweenTime, true);
-
this._blYTween = new Tween(this._bl, "y", this._tweenFunc, this._bl.y, $bl.y, this._tweenTime, true);
-
-
this._blYTween.addEventListener(TweenEvent.MOTION_CHANGE, render);
-
this._blYTween.addEventListener(TweenEvent.MOTION_FINISH, onFinished);
-
}
-
-
/**
-
* Resets the bitmap to the specified points.
-
*
-
* @usage <pre><code>dt.reset(new Point(0, 0), new Point(clip_mc.width, 0), new Point(clip_mc.width, clip_mc.height), new Point(0, clip_mc.height));</code></pre>
-
*
-
* @param $tl The top left point to use in the distortion
-
* @param $tr The top right point to use in the distortion
-
* @param $br The bottom right point to use in the distortion
-
* @param $bl The bottom left point to use in the distortion
-
*
-
* @return Nothing
-
*/
-
-
public function reset($tl:Point, $tr:Point, $br:Point, $bl:Point):void
-
{
-
this._tl = $tl;
-
this._tr = $tr;
-
this._br = $br;
-
this._bl = $bl;
-
-
this._container.graphics.clear();
-
this._holder.removeChild(this._container);
-
-
this._container = null;
-
this._container = new Shape();
-
-
this._holder.addChild(this._container);
-
}
-
-
/**
-
* Cleans up the DistortionTweener for garbage collection.
-
*
-
* @usage <pre><code>dt.destroy();</code></pre>
-
*
-
* @return Nothing
-
*/
-
-
public function destroy():void
-
{
-
this._bmd.dispose();
-
-
this._container.graphics.clear();
-
this._holder.removeChild(this._container);
-
-
this._bmd = null;
-
this._bmp = null;
-
this._container = null;
-
this._holder = null;
-
this._distortion = null;
-
}
-
-
//- EVENT HANDLERS ----------------------------------------------------------------------------------------
-
-
// Dispatched during the MOTION_CHANGE event to update the distorted graphics.
-
private function render($evt:TweenEvent):void
-
{
-
this._container.graphics.clear();
-
this._distortion.setTransform(this._container.graphics, this._bmp.bitmapData, this._tl, this._tr, this._br, this._bl);
-
}
-
-
// Dispatches a COMPLETE event when the distortion is finished.
-
private function onFinished($evt:TweenEvent):void
-
{
-
this._blYTween.removeEventListener(TweenEvent.MOTION_CHANGE, render);
-
this._blYTween.removeEventListener(TweenEvent.MOTION_FINISH, onFinished);
-
-
this._tlXTween = null;
-
this._tlYTween = null;
-
this._trXTween = null;
-
this._trYTween = null;
-
this._brXTween = null;
-
this._brYTween = null;
-
this._blXTween = null;
-
this._blYTween = null;
-
-
this.dispatchEvent(new Event(Event.COMPLETE));
-
}
-
-
//- GETTERS & SETTERS -------------------------------------------------------------------------------------
-
-
-
-
//- HELPERS -----------------------------------------------------------------------------------------------
-
-
public override function toString():String
-
{
-
return "com.reintroducing.transitions.DistortionTweener";
-
}
-
-
//- END CLASS ---------------------------------------------------------------------------------------------
-
}
-
}
If you found this post useful, please consider leaving a comment, subscribing to the feed, or making a small donation.
36 Comments
Nice one Matt! Do note that I can't really take credit for the distortion-technique myself, DistortImage was originally written by Thomas Pfeiffer, I merely ported it to an Actionscript3.0 class.
That is absolutely correct. I forgot to mention that in my posts but if anyone reads the DistortImage credits, hopefully they will see that. Thanks Ruben.
Hi Matt,
SWEET! Can you please release an AS2 version of this, pretty please!?
please, please, please..... its all I really want for the holidays.... please!
Sorry WT, there wasn't any plans for an AS2 version of this really. You could probably convert it easily but you'd have to get Thomas Pfeiffer's AS2 DistortImage class as Ruben mentioned he used on his AS3 conversion and the rest should just be AS3 to AS2 code conversion. If I have some free time I may try to get it up but I've got a lot of other things in the works for the site that I'd rather get done first so when I do finally get free time I'm going to be working on those before I would an AS2 version of this.
[...] Download full source code and check examples. No Comments Leave a Commenttrackback addressThere was an error with your comment, please try again. name (required)email (will not be published) (required)url [...]
Hi!
I loved your class, but I have a problem with it.
I want to keep my MC after distorting it. It is important to me because in my project I'm distorting 5 clips, and I wrote a lot of code involving them. But when I'm finished with distorting, I guess my clip becomes trapped in container sprite. So I loose it when I call destroy method. Also I can't do anything with my MC's (like tween them) because they are in container.
Can you help me with that?
I would be very gratefull.
Best regards,
Vjekoslav Ratkajec
Hey Vjekoslav,
The DistortionTweener doesn't affect your clip, it makes a duplicate of your clip in the form of a BitmapData and it puts that in the container and runs the distortion on that. If you're using the code from my example, i specifically in there put code to hide the original movie clip and then show it after the transformation is complete, so all you would have to do in your code is to follow that same model.
now, if you're talking about distorting your clip and then trying to do things to the distorted clip, that won't work, because that can't take events or anything like that. the distortion tweener is only for tweening distortions to and from movie clips, you can't tween it into a distorted state and then do anything on it because your actual clip isnt the one being distorted. make sense?
Hi Matt,
thanks for the fast reply!
Well I found what was bothering me and why didn't clip appear after destorying it.
It's working fine now, but just to let you know, I added:
this._mc.visible = true;
in destroy method.
So mine working version of your class is:
public function destroy():void
{
this._bmd.dispose();
this._mc.visible = true;
this._container.graphics.clear();
this._holder.removeChild(this._container);
this._bmd = null;
this._bmp = null;
this._container = null;
this._holder = null;
this._distortion = null;
}
Thank you again, you helped me alot!
Best regards,
Vjekoslav Ratkajec
Hi Matt,
Can distortionTweener be used to recreate the Mac style squeeze transition as displayed here:
http://www.scottgmorgan.com/blog/index.php/2007/11/15/grant-skinners-osx-squeeze-effect-in-as3/
http://www.gskinner.com/blog/archives/2007/11/squeeze_effect.html
If so how? I've been trying at it but can't get it. Seems like easing for the top and bottom parts of the the slide are different in the osx style transition. And I don't think two distortionTweens can be applied to the same mc at the same time.
Is this effect possible with DistortionTweener or DistortImage classes?
Hey Evan,
Unfortunately you can't achieve that effect with it. You can get something similar (because the distortion is only applied to four points) but not that exact thing. You can use it to distort it into a trapezoidal shape and then tween the two top points out to form a rectangle, but thats about it.
Thanks for your prompt reply Matt and your generous contribution of Distortion Tweener to actionscripters. Your answer was a surprise to me as I had expected you to say that Mac style effect was doable but I definitely take your word for it.
I was hoping to have a Mac OS style "swoosh" transition effect for a little app I'm working on using the Distort Image or DistortionTweener but I now know better. I had thought that maybe DistortImage could do the trick with different easing and/or tweening values for top-r/l and bottomr/l at different rates but I have been saved a lot of frustration and time by knowing now that it is not doable.
The other displacement map way of doing it I found was too processor intensive on slower computers (even in AS3).
In your estimation, would the something similar way of doing it with Distortion Tweener be as spectacular? What kind of even more spectacular slide transitions could be developed with Distortion Tweener then?
Evan,
I think something to look into which would maybe give you a similar effect (or something close) would be perlin noise and applying it to the movie clip you want to distort. Unfortunately I don't know off the top of my head how exactly youd go about it but if you play with it you may be able to get something close.
Have you downloaded and looked at Grant Skinner's file? I didn't but I'd imagine you could probably repurpose that somehow. Grant is a great coder so I'm sure you could go off of his files or maybe even ask him for some help.
Hi.
i`m kinda new to this, But is it possible to add a delay beefore the animation starts..?
-Kristian
Kristian,
Sure, before calling the tweenTo method just set your delay or call tweenTo anywhere you want it to happen in your code.
hi there,
great class. i just been think that you could replace the type of both the holder and the mc by DisplayObject. there is no need for a MovieClip, and the holder has to be a DisplayObject. anyways thanks for your effort, i will definitely use this class in upcoming projects.
cheers, jan
ooops. i'm sorry the holder of cource need to be at least a DisplayObjectContainer for the addchild method. stupid me.
Yow,
I'm new here today. i hope you could still reply. I'm reviewing your example 3 and practicing it. I'm trying to use Oval shapes but i can't seem to show the whole circle when i place this code:
"var dt:DistortionTweener = new DistortionTweener(c, oval_mc1, new Point(0, 0), new Point(oval_mc1.width, 0), new Point(oval_mc1.width, oval_mc1.height), new Point(0, oval_mc1.height), 5);"
whenever i do this without continuing the remaining bottom parts of the script it seems to show only 1/4 of the whole object(from center of the oval to bottom right). I'm not really sure if there should be a change on the x and y axis, i've tried but it seems to distort it way to much and still shows 1/4 of the whole oval.
Do you think its possible to Distort Ovals? if it is what should i change to show the whole oval?
Hey,
I've already figured why its not showing. Its seems that you just have to register the conversion of the movie clip symbol to top left and not center. Anyway, thanks for this review! Hopefully i could come up with something great with this! Peace!
[...] AS3: DistortionTweener Posted on 08.22.2008 to AS3 Subscribe to comments Comment | Trackback | SHARETHIS.addEntry({ title: "AS3 Effects", url: "http://www.mikkolehtinen.com/as3/as3-effects/" }); [...]
dear matt,
awesome class! one little question though: i have a hard time using your class when i use .flv instead of pictures to transform. the video gets stuck in the first frame although the audio is still going on, so the movie is obviously playing somewhere, but i cannot see it. is there a way to use this with .flv?
thanks a lot in advance,
marc
@marc: I don't believe that would work. What happens is it takes a screenshot of the clip you're distorting and draws it to a bitmapdata object which is the one you're distorting while hiding the original object. this is why the audio is still playing but the video seems "frozen" on the first frame. its hidden but hiding video doesnt stop audio. unfortunately this class won't handle what you want to do, sorry :\
Hi!
Ive just started usign your class, and some easing functions work fine (Elastic, for example), while for others I get the following error:
1120: Access of undefined property Cubic.
Do you know why this could be?
@lora: make sure you're importing the classes for the easing methods you want to use at the top of your file.
Dear Matt,
thank you very much for your answer. I tried to implement an update funcition, that refreshes the screenshot made of the clip i am distorting to make your class working with flvs, but i cannot get it to work. Do you have any idea how to approach this?













[...] here for [...]