Home > ActionScript 3, flash, general, utils > pause Timer with ExtendedTimer in ActionScript 3.0

pause Timer with ExtendedTimer in ActionScript 3.0

hey guys, last week i needed to pause several timers and resume them later on. i ran into a problem which i try to explain in an little example.

so let’s say you start a Timer with 1000 milliseconds delay and stop it after 600 milliseconds. if you call Timer.start() again, it starts with a new delay of 1000 milliseconds again. there is no built-in possibility to resume the timer for the remaining 400 milliseconds. i thought “nothing easier than that, just call Timer.pause()”. but there was no such method, so i decided to write my own ExtendedTimer class and add the pause functionality. now i like to share it with you…

> ExtendedTimer.as
package com.fjakobs.utils
{
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * @author fjakobs
	 */
	public class ExtendedTimer extends Timer
	{
		private var _startTime : Number;
		private var _initialDelay : Number;
		private var _paused : Boolean = false;

		public function ExtendedTimer(delay : Number,
									  repeatCount : int = 0)
		{
			super(delay, repeatCount);
			_initialDelay = delay;
			addEventListener(TimerEvent.TIMER,
						    onTimer,false,0,true);
		}

		private function onTimer(event : TimerEvent) : void
		{
			_startTime = new Date().time;
			delay = _initialDelay;
		}

		override public function start() : void
		{
			if(currentCount < repeatCount)
			{
				_paused = false;
				_startTime = new Date().time;
				super.start();
			}
		}

		public function pause() : void
		{
			if(running)
			{
				_paused = true;
				stop();
				delay = delay - (new Date().time - _startTime);
			}
		}

		public function get paused() : Boolean
		{
			return _paused;
		}

		public function get initialDelay() : Number
		{
			return _initialDelay;
		}
	}
}
  • Digg
  • del.icio.us
  • Blogosphere News
  • Facebook
  • LinkedIn
  • MySpace
  • Netvibes
  • Twitter
  1. thetoke
    October 30th, 2008 at 16:06 | #1

    I’d rather make it:

    delay = event.target.currentCount;

  2. October 30th, 2008 at 17:03 | #2

    why exactly would you do this?

  3. Nikita
    November 1st, 2008 at 09:07 | #3

    Thanks for code. But there’s little bug – then repeatCount reaches it’s maximum, method start() will trigger anyway. I added:
    override public function start() : void {
    if(currentCount < _repeatCount){
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }
    where _repeatCount is repeatCount from consructor. Now it’s work fine.

  4. November 3rd, 2008 at 10:19 | #4

    hey – make it a static function, and you’re a genius! :)

  5. November 4th, 2008 at 10:05 | #5

    @Nikita, thank you for the tip, i updated the start method. now the timer won’t trigger if you call start() after the timer reaches it’s maximum repeatCount.

    @grabek, do you think about a TimerManager?

  6. November 12th, 2008 at 11:23 | #6

    Another slight issue I faced is that in :

    override public function start() : void
    {
    if(currentCount < _repeatCount)
    {
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }

    … the “if” will never return true if _repeatCount is 0 since currentCount and and _repeatCount have the same value initally. Appending

    || _repeatCount == 0

    to the if statement solved the problem for me.

  7. November 12th, 2008 at 11:28 | #7

    Oh, and needless to say: Lovely piece of code. Thanks a lot. :)

  8. November 17th, 2008 at 07:37 | #8

    TimerManager – I suppose so! (:

  9. Peter
    December 15th, 2008 at 17:52 | #9

    Hey, thanks for this class!!! But, I’m newbie in AS3, classes!

    How I use this code in my class document after import it?

    (sorry for my poor english… I’m brazilian)

  10. Peter
    December 15th, 2008 at 18:12 | #10

    Yep! It’s works fine here now! Thanks!!!

  11. February 17th, 2009 at 04:22 | #11

    very useful class. Thanks! I had to add this:

    public function pause():void {
    if (running) {
    _paused = true;
    stop();
    var thisDelay:Number = delay – (new Date().time – _startTime);
    if (thisDelay < 0) {
    thisDelay = 0;
    }
    delay = thisDelay;
    }
    }

    I kept getting errors when var delay was below 0.

  12. Paul
    February 24th, 2009 at 01:35 | #12

    Very useful thanks so much!!

  13. Paul
    February 24th, 2009 at 01:42 | #13

    @Peter – might be a little late but this is how you use it.

    Once you import the class do the following.

    1. Create a var with type Number and set it to how long you want the timer delay.

    var newTimer:Number = 5000; //timer will run every 5sec

    2. create a new instance of ExtendedTimer and pass in the timer var you just created above.

    var timer1:ExtendedTimer = new ExtendedTimer(newTimer);

    3. Now just use timer1.start(); and timer1.pause(); to pause the timer. To resume simply call timer1.start(); again.

    That should do it! Good Luck

  14. Daniel
    March 1st, 2009 at 14:57 | #14

    Thank you, saved me some time :)

  15. Jason
    March 17th, 2009 at 21:40 | #15

    This saved me a lot of hair pulling and time.

    I needed the ability to reset this ExtendedTimer after it was paused but calling reset() didn’t reset the timer. I realized that was because you are adjusting the delay whenever start() was called.

    I created a new function called resume() which acts like your start() function. I then modified your start() function to set delay = _initialDelay; This essentially resets the timer.

    // timer continues from where it left off
    public function resume() : void
    {
    if((currentCount < repeatCount) || (repeatCount == 0))
    {
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }

    // timer gets reset
    override public function start() : void
    {
    if((currentCount < repeatCount) || (repeatCount == 0))
    {
    delay = _initialDelay; // added to “reset” timer
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }

    So now I can either call start() which always resets the timer or I can call resume() which resumes the timer.

    Thanks again for the code!

  16. Dennis
    May 28th, 2009 at 04:29 | #16

    I used this code to fix up my own pausable timer – very helpful, thanks :)
    I also encountered the “delay 0) //if there’s no remainder, timer should start next cycle
    {
    delay = remainder; //otherwise, timer should finish current cycle
    }

  17. axaq
    July 3rd, 2009 at 11:56 | #17

    that is really usefull. thank you..

  18. July 29th, 2009 at 15:42 | #18

    Hello man,

    I made it too :)

    http://blog.ramonfritsch.com/t/timer-com-pause

    cheers

  19. Dave
    August 6th, 2009 at 16:00 | #19

    Great little class. Just one thing I’d like to add which may be useful to others. I found that if I’d set the delay after the class was instantiated, then the specified delay would only work once, and afterwards it would revert to the original delay that was specified when the class was created. After adding the following, the problem was solved :)

    override public function set delay(n:Number):void {
    super.delay = n;
    _initialDelay = n;
    }

  20. Dave
    August 19th, 2009 at 15:54 | #20

    I should also mention that if you implement my fix from above, then you should change line 46 to:
    super.delay = delay – (new Date().time – _startTime);
    …unless you also use DorkBot’s fix (recommended), then change his line delay = thisDelay; into super.delay = thisDelay;

  21. btb
    August 23rd, 2009 at 22:09 | #21

    does anyone have a stable, complete, working, tested, etc, version of this? I see a bunch of evolution going on, wondering if I could get a final version? thanks to all

  22. September 4th, 2009 at 20:07 | #22

    Here is the version I compiled with all of the above changes. It seems to be working great! Hope this helps everyone. I know this has been a huge benefit to me!
    -Kipp

    ——————

    package com.fjakobs.utils
    {
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    /**
    * @author fjakobs
    */
    public class ExtendedTimer extends Timer
    {
    private var _startTime : Number;
    private var _initialDelay : Number;
    private var _paused : Boolean = false;

    public function ExtendedTimer(delay : Number, repeatCount : int = 0)
    {
    super(delay, repeatCount);
    _initialDelay = delay;
    addEventListener(TimerEvent.TIMER, onTimer, false, 0, true);
    }

    private function onTimer(event : TimerEvent) : void
    {
    _startTime = new Date().time;
    delay = _initialDelay;
    }

    // timer gets reset
    override public function start() : void
    {
    if((currentCount < repeatCount) || (repeatCount == 0))
    {
    delay = _initialDelay; // added to “reset” timer
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }

    public function pause() : void
    {
    if(running)
    {
    _paused = true;
    stop();
    var newDelay:Number = delay – (new Date().time – _startTime);
    super.delay = (newDelay < 0) ? 0 : newDelay;
    }
    }

    // timer continues from where it left off
    public function resume() : void
    {
    if((currentCount < repeatCount) || (repeatCount == 0))
    {
    _paused = false;
    _startTime = new Date().time;
    super.start();
    }
    }

    override public function set delay(n:Number):void {
    super.delay = _initialDelay = n;
    }

    public function get paused() : Boolean
    {
    return _paused;
    }

    public function get initialDelay() : Number
    {
    return _initialDelay;
    }
    }
    }

  23. November 16th, 2009 at 20:48 | #23

    Thanks for the compilation Kipp!

  24. Tommy
    December 1st, 2009 at 13:39 | #24

    hi there

    I’m using Kipp’s compilation to the letter. Everything seems to be working fine but i get an error nonetheless.
    Can anyone help?

    RangeError: Error #2066: The Timer delay specified is out of range.
    at Error$/throwError()
    at flash.utils::Timer/set delay()
    at com.fjakobs.utils::ExtendedTimer/pause()
    at be.figure8::SimpleSlideshow/pause()
    at pages::ShowPage/pauseEvent()

  25. Tommy
    December 4th, 2009 at 21:05 | #25

    It seems the error comes into play when the timer count gets reset.
    Try running a timer with an interval of 50ms and pause it every other second while looking at yr trace window.

    If anyone has an opinion about this error feel free to share, i have no idea why this is occurring.
    Kudos for the class! Gets the job done and is very usefull with minimal fancyness

  26. Roy
    January 13th, 2010 at 16:50 | #26

    Hi, Thanx for the tut. I am working on this with a project of mine but it doesn’t work.
    First I import the class:
    import com.fjakobs.utils.*
    Then I create the timer:
    var newTimer:Number = 5000;
    var slideTimer:ExtendedTimer = new ExtendedTimer(newTimer);
    function onSlideFadeIn():void {
    // check, if the slideshow is currently playing
    // if so, start the timer again
    if (bolPlaying && ! slideTimer.running) {
    slideTimer.start();
    }
    }

    I am using this class with this code showed on this website:
    http://www.thetechlabs.com/tutorials/xml/extending-the-as3flash9-slideshow-with-xml/

    I hope someone can help me with this,
    thanx

  1. October 16th, 2008 at 19:47 | #1