SitePoint Sponsor

User Tag List

Results 1 to 6 of 6
  1. #1
    SitePoint Enthusiast seezee's Avatar
    Join Date
    Jun 2010
    Location
    Oklahoma, USA
    Posts
    41
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Animation speeds up each time 'start' button clicked.

    I'm learning Javascript from Sitepoint's 'Simply Javascript' book. Just read the 1st animation example, which suggests one could add a 'start' & 'stop' (id="stopit") button to control the simple sprite animation. My Javascript looks like this (note that it works in tandem with the core.js that comes with the book; see the ZIP file i've attached):

    Code:
    var Robot =
    {
    	init: function() // initiate via core.js
    	{
    		Robot.div = document.getElementById("robot"); // the div containing the background sprite
    		Robot.frameHeight = 150;
    		Robot.frames = 10;
    		Robot.offsetY = 0;
        
    		{
    			var start = document.getElementById("start"); // the start button
    			Core.addEventListener(start, "click", Robot.clickStart, false); // add listener via core.js
    			var stopit = document.getElementById("stopit"); // the stop button
    			Core.addEventListener(stopit, "click", Robot.clickStop, false); // add listener via core.js
    		}
    	},
      
    	clickStart: function() // the animation function
    	{
    		Robot.offsetY -= Robot.frameHeight;
    		
    		if (Robot.offsetY <= -Robot.frameHeight * Robot.frames)
    		{
    			Robot.offsetY = 0;
    		}
    	
    		Robot.div.style.backgroundPosition = "0 " + Robot.offsetY + "px";
    	
    		Robot.timer = setTimeout(Robot.clickStart, 75);
    	
    	},
    	clickStop: function() // the killswitch
    	{
    		if (Robot.timer)
    		{
    			clearTimeout(Robot.timer);
    		}
    		
    		Robot.offsetY = 0;
    		Robot.div.style.backgroundPosition = "0 " + Robot.offsetY + "px"; // return the animation to the 1st frame
    		alert ("Aborted \u2014 must sleep now. Zzzz \u2026");
    	}
    };
    
    Core.start(Robot); //initiate via core.js
    Oddly, clicking on the 'start' button more than once speeds up the animation, more with each successive click. Clicking the 'stop' button will only finally stop the animation if it's done the same number of times as the 'start' button was clicked.

    Anyone know what causes this?

    Thanks,

    --cz
    Attached Files Attached Files

  2. #2
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Code:
    if (Robot.timer)
    {
     clearTimeout(Robot.timer);
    }
    I would say this block from the clickStop function should be copied into the beginning of the clickStart function.
    Tab-indentation is a crime against humanity.

  3. #3
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,702
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by seezee View Post
    Oddly, clicking on the 'start' button more than once speeds up the animation, more with each successive click. Clicking the 'stop' button will only finally stop the animation if it's done the same number of times as the 'start' button was clicked.

    Anyone know what causes this?
    Yes, each time you click on start you end up creating another event timer. So by the 3rd click you'll have three event timers all firing off individually, which is why things then go three times as fast.

    A way around this is to assign the event timer to a single known variable, so that multiple instances only replace the old one that was there previously. Commonly you would assign the timer to a named property on the object itself.

    Another alternative is to disable the start button as soon as it's pressed.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  4. #4
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by pmw57 View Post
    Y
    A way around this is to assign the event timer to a single known variable, so that multiple instances only replace the old one that was there previously.
    The OP's script does that already and it doesn't work. Re-assigning a timeout or interval to a variable does nothing except store an integer that can be used as an address by clearTimeout/clearInterval. It does not cancel any pending timer.
    Code:
    <html>
    <head>
    <title>Interval Overwrite Test</title>
    </head>
    <body>
    
    <div id='t' style='position:absolute;top:100px;left:0'>:-)</div>
    <script type='text/javascript'>
    
    var timer, x = 0 ;
    
    function a()
    {
     document.getElementById('t').style.left = (x+=2) % 500 + 'px';
       
     timer = setTimeout(a, 400);  
     
     return false; 
    }
    
    function stopAll( t )
    {
     for( var i=1; i<=t; i++)  
      clearTimeout( i ); 
      
     return false; 
    }
    
    
    </script>
    
    <p>
    <a href='#' onclick="return a()">START</a> &lt;- click repeatedly
    <p>
    <a href='#' onclick="return stopAll( timer )">STOP all timers</a>
    
    </body>
    </html>
    Tab-indentation is a crime against humanity.

  5. #5
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,702
    Mentioned
    101 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by Logic Ali View Post
    The OP's script does that already and it doesn't work. Re-assigning a timeout or interval to a variable does nothing except store an integer that can be used as an address by clearTimeout/clearInterval. It does not cancel any pending timer.
    My apologies, I should have been clearer.

    Whenever a timer is started, you need to first check that the timer doesn't already exist. If it does already exist you need to either replace it, but stopping the timer and starting a new one, or by doing nothing and allowing the exisiting timer to carry on as per normal.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  6. #6
    SitePoint Enthusiast seezee's Avatar
    Join Date
    Jun 2010
    Location
    Oklahoma, USA
    Posts
    41
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Logic Ali's original solution solution is simple and works. I thought I had already tried that yesterday without success, but apparently I hadn't.

    Also thanks for the 2nd solution + example script -- it's always good to know another way to do something.

    --cz


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •