Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hammer.js is slow and jerky on pinchin/pinchout

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

like image 947
CoolTapes Avatar asked Dec 19 '22 22:12

CoolTapes


1 Answers

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.

like image 98
Simon Boudrias Avatar answered Jan 03 '23 22:01

Simon Boudrias