2
\$\begingroup\$

I recently made this campus timeline for my university. When viewing the timeline on a mobile device (not a tablet), the navbar changes so that you can jump to the previous or next decade by clicking one of the arrows.

I'm concerned about the performance of the animation. I'm using a Samsung Galaxy S3 (one of the most powerful Android phones out) but it's still extremely sluggish in both Chrome and Dolphin browser. How can I make it faster? The code that controls the jump and animation can be viewed here:

$timeline.find(".dec-banner").on("click", "a", function(event) { // bring user to previous or next decade if clicked on in the decade header
    var $navlink = $(this).attr("href");
    if ($(this).parent().hasClass("decade-jump-prev")) {
        $("html,body").stop(true, true).animate({scrollTop: $($navlink).offset().top-43},"fast");
    }
    if ($(this).parent().hasClass("decade-jump-next")) {
        $("html,body").stop(true, true).animate({scrollTop: $($navlink).offset().top},"fast");
    }
    event.preventDefault();
});

Is this animation hardware accelerated? If not, can I somehow force it to be?

\$\endgroup\$
  • \$\begingroup\$ Randomly stumbled across this very old question of mine and now I can tell the past version of me and anyone else reading that jQuery's animate is extraordinarily inefficient and that I should have used something like Greensock to handle the animation. \$\endgroup\$ – Mister Oh Jul 29 '15 at 23:11
2
\$\begingroup\$
//html and body don't change in the lifetime of the page, no sense fetching them everytime
//thus we move it out of the handler into a static scope
var html_body = $('html,body');

//Use the context parameter and keep your code short. It acts like `find`.
//I suggest you delegate at a lower parent so bubbling won't travel that far.
//If `.dec-banner` is unique in the page, consider assigning it an `id` instead
//so we can directly access it, rather than find some `class` under some node
//Lastly, you can be more specific rather than listening for events on `a` elements
//that way, the handler won't execute on any `a` element under `.dec-banner`
$('.dec-banner', $timeline).on('click', 'a', function (event) {

  //for values that get used more than once, especially if they require DOM fetching
  //cache their values in variables. In this case, `$(this)` and parent gets used more than once
  var $this = $(this);
  var navlink = $($this.attr('href'));
  var parent = $this.parent();

  //we check for the existence of these classes to determine the fix
  var prev = parent.hasClass('decade-jump-prev');
  var next = parent.hasClass('decade-jump-next');

  event.preventDefault();

  //evaluate if they are prev and next once, rather than twice
  //we can't use the *return early* approach for avoiding indention
  //since propagation might be used
  if (prev || next) {

    //within this block, we assume that the links are either prev or next
    //if not prev, then it should be next

    html_body.stop(true, true).animate({
      //we adjust the fix depending on the existence of prev and next
      //if prev, we use 43, otherwise 0
      scrollTop: navlink.offset().top - (prev ? 43 : 0)
    }, 'fast');
  }


});
\$\endgroup\$
  • \$\begingroup\$ this is fantastic! thank you very much. i'm in the beginning stages of learning javascript/jquery so this was extremely helpful. \$\endgroup\$ – Mister Oh Apr 29 '13 at 18:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.