SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)

    Javascript Animation Using the While Loop??... Can this Work ??

    Aloha.

    Okay so I'm not in the mood to have to write a million functions and set time-outs and intervals and all of that.

    So here I am trying to achieve a simple Javascript animation using just the while loop in one function.

    1. The function is supposed to read the name of the layer to affect.

    2. Then it records the layer's current height and inner-HTML.

    3. Then it moves the layer into place and simultaneously...

    4. ...makes its height zero and clears its inner-HTML.

    5. Then the while loop is supposed to incrementally increase the layer's height until it's back to its initial value.

    6. Finally, the inner-HTML is restored to its recorded value.

    The over-all effect is meant to be that of an unsliding menu.



    Here is my Javascript...

    Code JavaScript:
    function toggleDrawer(drawer_ID,drawer_XPos,drawer_YPos)
    	{
    	drawer_FinalHeight = (document.getElementById(drawer_ID).style.height);
    	drawer_FinalContents = (document.getElementById(drawer_ID).innerHTML);
    	drawer_CurrentHeight = ('0');
    	drawer_CurrentContents = ('');
     
    	document.getElementById(drawer_ID).style.left = drawer_XPos+"px";
    	document.getElementById(drawer_ID).style.top = drawer_YPos+"px";
     
    	document.getElementById(drawer_ID).innerHTML = drawer_CurrentContents;
     
    	while (drawer_CurrentHeight+"px" <= drawer_FinalHeight)
    		{
        	document.getElementById(drawer_ID).style.height = drawer_CurrentHeight+"px";
    		drawer_CurrentHeight = (drawer_CurrentHeight + 1);
    		wait(5000);
    		}
    	}

    ...here is my HTML...
    Code HTML4Strict:
    				<!-- Drawer2 Layers -->
    				<div id="Drawer2">
    					<div id="Drawer2_Services">Services</div>
    					<div id="Drawer2_Products">Products</div>
    					<div id="Drawer2_Articles">Articles</div>
    				</div>
    				<!-- End Drawer2 Layers -->

    ...and here is my CSS...
    Code CSS:
    #Drawer2{position:absolute;}
    #Drawer2_Services{position:absolute; left:0px; top:0px; width:180px; height:300px; background:#990000;}
    #Drawer2_Products{position:absolute; left:0px; top:0px; width:180px; height:200px; background:#990000;}
    #Drawer2_Articles{position:absolute; left:0px; top:0px; width:180px; height:100px; background:#990000;}



    Please give this a try yourself.

    For whatever reason, even though I have that while loop with that wait(5000); command, it appears that the loop runs superfast and restores the layer's height in a millisecond.

    It therefore doesn't look animated at all... it looks as though the layer instantly moved and nothing else.

    Can anyone follow my hair-brained maddness?? Can anyone give me any pointers to get this working??



    Many thanks in advance.

  2. #2
    SitePoint Evangelist hexburner's Avatar
    Join Date
    Jan 2007
    Location
    Belgium
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You'll have to use setInterval to do this. In JavaScript there's nothing like wait() or sleep(), you have to use setInterval or setTimeout for this to work properly. Someone mentioned once you can implement wait() by using an XmlHttpRequest, but that's something you really don't need.

    You only need two functions and the setInterval for what you want.
    One function initializes the animation: gets the element, stores the element in a variable so you don't have to get the element every time the animation goes further, define your other variables, ... and of course a variable to store the interval in so you can clear the interval after the animation is done.

    The second function then uses the function setInterval() to animate at the speed you want (by stopping 75 ms after every time the function has been executed for example). At the end of the animation you clear the interval you've stored so the animation stops and the function won't be executed automatically anymore.
    FOR SALE: 1 set of morals, never used, will sell cheap

  3. #3
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)
    I feared as much.

    I had done a layer animation some years ago like this... with the setInterval(); function.

    I really was hoping I could knock together something quick but I guess not.

    Thanks for the advice, man. I'll exhume up my old script.



    Last edited by Shaun(OfTheDead); Jul 7, 2007 at 14:17.

  4. #4
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)
    Right...

    So here's why I hate using multiple functions...


    Code JavaScript:
    function toggleDrawer(drawer_ID,drawer_XPos,drawer_YPos)
    	{
    	/* Define Variables */
    	drawer_FinalHeight = (document.getElementById(drawer_ID).style.height);
    	drawer_FinalContents = (document.getElementById(drawer_ID).innerHTML);
    	drawer_CurrentHeight = ('0');
    	drawer_CurrentContents = ('');
     
    	/* Move Drawer into Position */
    	document.getElementById(drawer_ID).style.left = drawer_XPos+"px";
    	document.getElementById(drawer_ID).style.top = drawer_YPos+"px";
     
    	/* Initialise Drawer for Opening */
    	document.getElementById(drawer_ID).innerHTML = drawer_CurrentContents;
    	document.getElementById(drawer_ID).style.height = drawer_CurrentHeight+"px";
    	document.getElementById(drawer_ID).style.display = "block";
     
    	openInterval = window.setInterval('openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents);',1);
    	}
     
     
     
    function openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents)
    	{
    	alert(drawer_ID);
    	alert(drawer_FinalHeight);
    	alert(drawer_FinalContents);
     
    	window.clearInterval(openInterval);
    	}

    How can I export the variables from my toggleDrawer(); into the openDrawer(); function??

    It works fine without the setInterval... for example when I had...


    Code JavaScript:
    function toggleDrawer(drawer_ID,drawer_XPos,drawer_YPos)
    	{
    	/* Define Variables */
    	drawer_FinalHeight = (document.getElementById(drawer_ID).style.height);
    	drawer_FinalContents = (document.getElementById(drawer_ID).innerHTML);
    	drawer_CurrentHeight = ('0');
    	drawer_CurrentContents = ('');
     
    	/* Move Drawer into Position */
    	document.getElementById(drawer_ID).style.left = drawer_XPos+"px";
    	document.getElementById(drawer_ID).style.top = drawer_YPos+"px";
     
    	/* Initialise Drawer for Opening */
    	document.getElementById(drawer_ID).innerHTML = drawer_CurrentContents;
    	document.getElementById(drawer_ID).style.height = drawer_CurrentHeight+"px";
    	document.getElementById(drawer_ID).style.display = "block";
     
    	openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents);',1);
    	}

    ...my two functions executed error free.

    With the setInterval, though, all of a sudden my variables aren't being recognised in the second function anymore.

    What do you make of this??

  5. #5
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    You have to do this:
    Code Javascript:
    window.setInterval(function() {
      openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents);
    } ,1);
    Something to do with setInterval being a property of the window object and loss of the current scope when you call it. BTW, about that interval of one millisecond, browsers can't do it that fast. I suppose it depends on the hardware, but I think I remember reading somewhere that browsers have an internal limit, which I think is around 50 ms.

  6. #6
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)
    Outstanding.

    Thanks, Raf'.

  7. #7
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)
    Okay... here's the final thing.

    I had to change my HTML and define the heights of the layers in there because for whatever reason it wasn't working when I had the heights defined in the external stylesheet.


    Code HTML4Strict:
    				<!-- Drawer2 Layers -->
    				<div id="Drawer2">
    					<div id="Drawer2_Services" style="height:120px;">Services</div>
    					<div id="Drawer2_Products" style="height:200px;">Products</div>
    					<div id="Drawer2_Articles" style="height:300px;">Articles</div>
    				</div>
    				<!-- End Drawer2 Layers -->

    My external stylesheet is now this, therefore...
    Code CSS:
    #Drawer2{position:absolute;}
    #Drawer2_Services{display:none; position:absolute; left:0px; top:0px; width:180px; background:#990000;}
    #Drawer2_Products{display:none; position:absolute; left:0px; top:0px; width:180px; background:#990000;}
    #Drawer2_Articles{display:none; position:absolute; left:0px; top:0px; width:180px; background:#990000;}

    Finally I needed to add one more function called seekHeight(); to the duo because without it for some reason the heights of the layers were increasing exponentially. Very strange.

    Here it is...

    Code JavaScript:
    function seekHeight(drawer_ID)
    	{
    	drawer_CurrentHeight = document.getElementById(drawer_ID).style.height;
    	drawer_CurrentHeight = parseInt(drawer_CurrentHeight);
    	drawer_CurrentHeight = (drawer_CurrentHeight * 1);
    	}
     
     
    function toggleDrawer(drawer_ID,drawer_XPos,drawer_YPos)
    	{
    	/* Define Variables */
    	drawer_FinalHeight = document.getElementById(drawer_ID).style.height;
    	drawer_FinalHeight = parseInt(drawer_FinalHeight);
    	drawer_FinalHeight = (drawer_FinalHeight * 1);
    	drawer_FinalContents = (document.getElementById(drawer_ID).innerHTML);
    	drawer_CurrentContents = ('');
     
    	/* Move Drawer into Position */
    	document.getElementById(drawer_ID).style.left = drawer_XPos+"px";
    	document.getElementById(drawer_ID).style.top = drawer_YPos+"px";
     
    	/* Initialise Drawer for Opening */
    	document.getElementById(drawer_ID).innerHTML = drawer_CurrentContents;
    	document.getElementById(drawer_ID).style.height = "0";
    	document.getElementById(drawer_ID).style.display = "block";
     
    	/* Execute */
    	openInterval = window.setInterval(function(){openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents);},1);
    	}
     
     
    function openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents)
    	{
    	seekHeight(drawer_ID);
     
    	if(drawer_CurrentHeight <= drawer_FinalHeight)
    		{
    		newCurrentHeight = (drawer_CurrentHeight + 10);
    		drawer_CurrentHeight = newCurrentHeight;
    		document.getElementById(drawer_ID).style.height = newCurrentHeight+"px";
    		}
    	else
    		{
    		window.clearInterval(openInterval);
    		}
    	}

    Thanks for help.

    By the way, Raf', I don't know if the 1 millisecond is real speed it's running, but it's moving faster than when I had it set to 50... I don't think 50 is the limit.

  8. #8
    I meant that to happen silver trophybronze trophy Raffles's Avatar
    Join Date
    Sep 2005
    Location
    Tanzania
    Posts
    4,662
    Mentioned
    2 Post(s)
    Tagged
    0 Thread(s)
    Since you don't like having extra functions, you could just incorporate that one into openDrawer. parseInt returns an integer, so you don't need to multiply by 1.

    Code Javascript:
    function openDrawer(drawer_ID,drawer_FinalHeight,drawer_FinalContents)
        {
        var drawer_CurrentHeight = parseInt(document.getElementById(drawer_ID).style.height);
     
        if(drawer_CurrentHeight <= drawer_FinalHeight)
            {
            newCurrentHeight = (drawer_CurrentHeight + 10);
            drawer_CurrentHeight = newCurrentHeight;
            document.getElementById(drawer_ID).style.height = newCurrentHeight+"px";
            }
        else
            {
            window.clearInterval(openInterval);
            }
        }

    But you actually don't need that at all. The thing is you can't get things defined in the stylesheet using the "style" object. (something.style = "property") That's only for when it's specified inline, like you're doing with the height. You can have it in the stylesheet, you just have to get it in another way. With IE you would use element.currentStyle.height and with other browsers you would use
    Code:
    document.defaultView.getComputedStyle(element, null).getPropertyValue('height')
    One thing to note there is that IE returns it as a pixel value (a naked number) whereas getComputedStyle returns it as a string including the units, so you would have to parseInt it. Alternatively you can also use one of these:
    Code:
    element.clientHeight (height plus padding)
    element.offsetHeight (height plus padding plus border height)
    If you have no padding or borders they should be the same.

  9. #9
    Keep Moving Forward gold trophysilver trophybronze trophy
    Shaun(OfTheDead)'s Avatar
    Join Date
    Nov 2005
    Location
    Trinidad
    Posts
    3,727
    Mentioned
    43 Post(s)
    Tagged
    0 Thread(s)
    I can safely say I did not know about that getComputedStyle function.

    I'll look it up in a few minutes.


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
  •