Could anyone advise the best way to trigger a functiont when a movieclip animation finishes? I figure an eventlistener could handle this, but not sure the best way to go abo
There are a few ways to go about this:
In reference to point 3, I would create a base class for your object. This way you can apply the same logic to multiple elements being animated.
Something like this:
package
{
import flash.display.MovieClip;
import flash.events.Event;
public class AnimatingObject extends MovieClip
{
// constants
public const ANIMATION_COMPLETE:String = "animation_complete";
/**
* Constructor
*/
public function AnimatingObject()
{
addEventListener(Event.ENTER_FRAME, _handle);
}
/**
* Called on dispatch of Event.ENTER_FRAME
*/
private function _handle(e:Event):void
{
if(currentFrame == totalFrames)
{
var evt:Event = new Event(ANIMATION_COMPLETE);
dispatchEvent(evt);
}
}
}
}
Now we can listen for "animation_complete" and do stuff accordingly.
package
{
import flash.events.Event;
public class MyAnimatingObject extends AnimatingObject
{
/**
* Constructor
*/
public function MyAnimatingObject()
{
addEventListener(ANIMATION_COMPLETE, _lastFrame);
}
/**
* Called on dispatch of AnimatingObject.ANIMATION_COMPLETE
*/
private function _lastFrame(e:Event):void
{
trace("i'm done");
}
}
}
It's been awhile since I played with flash. I mostly do flex now, but this should work.
Using the enterFrame Event would be a huge waste of resources, and creating a custom event class is not nessesary.
On the last frame put this
dispatchEvent(new Event("INSERTSTUPIDEVENTNAMEHERE"));
And in your code on your "root"
movieInstanceName.addEventListener( "INSERTSTUPIDEVENTNAMEHERE", someCallBackFunction );
function someCallBackFunction ( e:Event ):void{
trace( "Last frame hit");
}
Only check currentFrame
and totalFrames
is not enough for a MovieClip that has multiple scenes. You must also check if it is at the last scene.
function isAtLastFrame(mc:MovieClip):Boolean
{
return currentScene.name == mc.scenes[mc.scenes.length - 1].name && currentFrame == currentScene.numFrames;
}
By making use of an ENTER_FRAME listener, you can tell if a MovieClip has readed the end of playback; you can then take this one step further by wrapping it up in a Wrapper class that will perform the monitoring for you:
public class EndOfMovieClipEventDispatcher extends EventDispatcher
{
private var target : MovieClip;
private var endReachedEvent : String;
public function EndOfMovieClipEventDispatcher(target : MovieClip, endReachedEvent : String = "complete") {
this.target = target;
this.endReachedEvent = endReachedEvent;
target.addEventListener(Event.ENTER_FRAME, onEnterFrameEvent, false, 0, true);
}
public function destroy() : void {
target.removeEventListener(Event.ENTER_FRAME, onEnterFrameEvent);
}
private function onEnterFrameEvent(event : Event) : void
{
if (target.currentFrame == target.totalFrames) {
dispatchEvent(new Event(endReachedEvent));
}
}
}
Usage is pretty straight forward; the call to destroy() is optional thanks to the weak event listener; but recommended if you are finished :)
new EndOfMovieClipEventDispatcher(myMovieClip).addEventListener(Event.COMPLETE, onMovieClipCompleteEvent);
myMovieClip.play();
You could use an enterframe listener that checks to see if the movieclip's currentFrame == totalFrames, and if they are equal, dispatch a custom event that you make (like TimelineComplete).
Another option would be to create a small component that dispatches your custom TimelineComplete event, and place that component on the final frame of any animation you'd like to monitor. This would allow you to get more creative in the future and add things like a delay before the event is triggered.
You've got a few options, none of which are ideal in my opinion, however they do work, and if done well they won't become unwieldy. The one thing I wouldn't do is add a little bit of code on the last frame. That gets rather hard to keep track of over time.
if looking for shortest solution i think it would be :
mc.addFrameScript(mc.totalFrames - 1, function():void
{
trace("end of mc");
});