4

I'm using hammer.js to implement some touchscreen functionality on a pet project.

The desired product is a map that can be dragged around and zoomed in and out with a touchscreen. I got it working, and everything is nice except the pinchin/pinchout mechanics are very, very slow. There is a very noticeable delay between when the pinch happens, and when the event fires.

Here's the relevant JQuery/JS code:

EDIT: Code is way nicer (and faster) now per Simon's suggestions. Here's the finished version

$(document).ready(function(){
  //Function which simulates zoom on the map on pinchin/pinchout
  $('#map').hammer()
    .on("pinchin", function(e) {
      var scale = $(this).css('transform');
      scale = (scale == null ? $(this).css('-webkit-transform') : scale); 
      scale = (scale == null ? $(this).css('-ms-transform') : scale);
      scale = scale.split(" ");
      scale = parseFloat(scale[0].substring(7, scale[0].length - 1));

      if(scale > 1) {
        scale = ('scale(' + (scale - .1).toString() + ')');
        $(this).css({'transform':scale, '-ms-transform':scale, '-webkit-transform':scale });
      }
    })
    .on("pinchout", function(e) {
      var scale = $(this).css('transform');
      scale = (scale == null ? $(this).css('-webkit-transform') : scale); 
      scale = (scale == null ? $(this).css('-ms-transform') : scale);
      scale = scale.split(" ");
      scale = parseFloat(scale[0].substring(7, scale[0].length - 1));

      if(scale < 5) {
        scale = ('scale(' + (scale + .1).toString() + ')');
        $(this).css({'transform':scale, '-ms-transform':scale, '-webkit-transform':scale
      }
  });
});

hammer.js documentation

3
  • Can you tell me please witch version of hammer you use in the above example, because when i use the latest one i got error "Object [object Object] has no method 'hammer'"
    – Abou-Emish
    Commented Jan 17, 2014 at 13:58
  • @MohamedS.AbuEmesh If you simply try the demo on the hammerjs web site you will see that if you repeatedly do pinchin and pinchout, the detected gesture becomes many seconds delayed. This is specific to pinchin and pinchout. Tested on Android with Firefox.
    – user239558
    Commented Feb 10, 2014 at 23:50
  • 1
    Thanks, now i'm using iScroll 5 and it's working good on Android, IPhone, and IPad.
    – Abou-Emish
    Commented Feb 11, 2014 at 8:17

1 Answer 1

12

This is jerky because you make way to much computation in each event handler.

First, cache your variables. calling $('#map') always goes in the DOM, get the object and return it. Only do this once, cache the result.

Same thing after with your calculations. Don't call this a[0] + a[7] all the time, calculate once, apply multiple time.

Then, well, combine your .css() calls in only one call with multiple attributes.

That'll help, but to get something silky smooth, read on:


Having smooth animation is not so hard, but you need to understand where to improve and how to limit layout cost, reflow and relayout. I can't explain all this here, but I can give you some concepts to research:

First of all, use requestAnimationFrame before firing any css changes. This will ensure the css modifications happens at the beginning of an animation frame, not at the end - so it helps reducing the risk of skipping a frame.

Then, try to use css3 transformations as much as possible (I don't mean use CSS stylesheet, I mean use css3 property with JavaScript). These properties perform way better. At the same time, try removing most of costly CSS styles and test a lot as some have a high rendering time cost (like drop-shadow and such).

Then, check and read most Google dev team presentation on respecting a 60 fps rate, and anything about making your website jank free. They often present basic concepts who'll help you better understand what's going on, and where/how to optimize and track the performance of your site.

4
  • This worked, and I learned something. I was not aware you could make multiple css changes in one statement. Thanks
    – CoolTapes
    Commented Oct 18, 2013 at 17:27
  • Well, it's better. But still not smooth.
    – CoolTapes
    Commented Oct 18, 2013 at 17:29
  • Edited with some more suggestions. For you, the next big step would be passing these animations inside requestAnimationFrame. Then optimizing CSS style for performance, and maybe trying to find styling alternative to updating font-size, max-width, etc as they are pretty costly on repainting and causes reflows. Commented Oct 18, 2013 at 18:02
  • 1
    I changed the whole logic to use css3 transform:scale instead of manually resizing, and now it's very fast. Thanks for the help
    – CoolTapes
    Commented Oct 18, 2013 at 19:03

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