Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Smoothest way to move a div with JS/jQuery

I need to move a div from the right to the left of the screen, but using both classic JS and jQuery makes it jerky:

My divs:

<div class="lisp" id="lisp0" style="top:100px;">)</div>
<div class="lisp2" id="lisp1" style="top:300px;">)</div>

Classic javascript method:

function move()
{
  pos = parseInt($("#lisp1").css("right"));
  $("#lisp1").css("right", pos+10+"px");
}
var interval = setInterval("move()",10);

jQuery method:

$("#lisp0").animate({"left": "-=2200px"}, 10000);

I made a webpage to show you how jerky it is. The first move is with jQuery (the smoothest one), the second one with classic JS. With several divs (and classic JS), it starts to be really annoying. I tried to modify jQuery.fx.interval, but it doesn't really increase performances.

So my question is: what is the best way to make these divs move smoothly ?

like image 541
ldiqual Avatar asked Mar 06 '11 14:03

ldiqual


1 Answers

You asked me for an example to improve the speed, I'm not an expert but here is what I would do:

  1. Don't use setInterval with string functions, they have to run through eval to run, so use this instead. In fact I wouldn't use setInterval at all for the main loop (see point #3).

    setInterval(doSomething, 100)
    
  2. Store an object you will be using multiple times (especially in a function that loops constantly). Even this example is not ideal:

    var lisp = $('#lisp1');
    function move()
    {
     var pos = parseInt( lisp.css("right"), 10 ); // always use a radix
     lisp.css("right", pos + 10 + "px");
    }
    
  3. For functions that loop constantly, be as short and concise as possible and eliminate extra function calls. From your second link, I compressed this code:

    function move(){
          $(".lisp").each(function(){
    pos = parseInt($(this).css("right"));
        if (pos > width)
          $(this).remove();
        else
          $(this).css("right", pos+speed+"px")
      });
      $(".bonus").each(function(){
        pos = parseInt($(this).css("right"));
        if (pos > width)
          $(this).remove();
        else
          $(this).css("right", pos+speed+"px")
      });
      $(".special").each(function(){
        pos = parseInt($(this).css("right"));
        if (pos > width)
          $(this).remove();
        else
          $(this).css("right", pos+speed+"px")
      });
    }
    

    into this more concise version:

    function move(){
      $(".lisp, .bonus, .special").each(function(){
        var pos = parseInt(this.style.right || 0, 10);
        if (pos > width) {
          $(this).remove();
        } else {
          this.style.right =  pos + speed + "px";
        }
      });
      if (!over) { setTimeout(move, 10); } // use this instead of the setInterval()
    }
    

    It's still not ideal, because your code keeps adding more and more objects. It should be limited because at one point I have over 200 objects on the screen and the page came to a crawl. This is also why I would use the setTimeout in the last line instead of the setInterval you use because the script may not have cycled through all of the elements before you want it to start again.

I'm sure there are more points someone else could add to optimize my or your code even more :)

like image 112
Mottie Avatar answered Sep 29 '22 20:09

Mottie