Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinch to zoom using Hammer.js

I am trying to implement pinch to zoom using hammer.js

Here's my HTML-

 <script src="//cdnjs.cloudflare.com/ajax/libs/hammer.js/1.0.5/hammer.min.js"></script>  <div id="pinchzoom">         <div>             <img id="rect" src="http://blog.gettyimages.com/wp-content/uploads/2013/01/Siberian-Tiger-Running-Through-Snow-Tom-Brakefield-Getty-Images-200353826-001.jpg" width="2835" height="4289" ondragstart="return false" alt="" />         </div>     </div> 

Here's my SCRIPT

var hammertime = Hammer(document.getElementById('pinchzoom'), {         transform_always_block: true,         transform_min_scale: 1,         drag_block_horizontal: false,         drag_block_vertical: false,         drag_min_distance: 0     });      var rect = document.getElementById('rect');      var posX=0, posY=0,         scale=1, last_scale,         rotation= 1, last_rotation;      hammertime.on('touch drag transform', function(ev) {         switch(ev.type) {             case 'touch':                 last_scale = scale;                 last_rotation = rotation;                 break;              case 'drag':                 posX = ev.gesture.deltaX;                 posY = ev.gesture.deltaY;                 break;              case 'transform':                 rotation = last_rotation + ev.gesture.rotation;                 scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10));                 break;         }          // transform!         var transform =                 //"translate3d("+posX+"px,"+posY+"px, 0) " +                 "scale3d("+scale+","+scale+", 0) ";           rect.style.transform = transform;         rect.style.oTransform = transform;         rect.style.msTransform = transform;         rect.style.mozTransform = transform;         rect.style.webkitTransform = transform;     }); 

It works fine but I am not able to scroll the image. On uncommenting transform3d it works but image looses its position on drag. I can't use jQuery.

like image 426
nickalchemist Avatar asked Aug 02 '13 07:08

nickalchemist


People also ask

How do you pinch and zoom?

If you're a Premium member, you can find the new feature in the YouTube app on Android; just tap your profile photo and then hit Your Premium benefits. From there, you can find the Try new features page and turn on YouTube's pinch to zoom. It may take a while to kick in until you can give this new tool a shot.

Why hammer js is used?

“Hammer is an open-source library that can recognize gestures made by touch, mouse, and pointer events.” – hammerjs.github.io. It is a popular JavaScript library that can be used to build web applications that require performing actions like panning, swiping, rotating, and zooming on touch gestures.

What is Hammer min js?

js. A javascript library for multi-touch gestures.


2 Answers

For hammer.js 2.0+ I have taken @DGS answer and changed it to suit what I was doing with cordova and intel-xdk so it's pure JS and hammer.js 2.0 for webkit.

My implementation allows you to zoom and drag at the same time, not independent of each other as above, and provides for a more native feel. It also implements the double tap to zoom in (and to zoom back out). I have it set to zoom between .999 and 4, but you can do as you like just changing those values. So if you just copy and paste this it will probably do what you expect it to (on webkit).

Thanks to Eight Media and @DGS for getting me started! Feel free to improve it SO.

function hammerIt(elm) {     hammertime = new Hammer(elm, {});     hammertime.get('pinch').set({         enable: true     });     var posX = 0,         posY = 0,         scale = 1,         last_scale = 1,         last_posX = 0,         last_posY = 0,         max_pos_x = 0,         max_pos_y = 0,         transform = "",         el = elm;      hammertime.on('doubletap pan pinch panend pinchend', function(ev) {         if (ev.type == "doubletap") {             transform =                 "translate3d(0, 0, 0) " +                 "scale3d(2, 2, 1) ";             scale = 2;             last_scale = 2;             try {                 if (window.getComputedStyle(el, null).getPropertyValue('-webkit-transform').toString() != "matrix(1, 0, 0, 1, 0, 0)") {                     transform =                         "translate3d(0, 0, 0) " +                         "scale3d(1, 1, 1) ";                     scale = 1;                     last_scale = 1;                 }             } catch (err) {}             el.style.webkitTransform = transform;             transform = "";         }          //pan             if (scale != 1) {             posX = last_posX + ev.deltaX;             posY = last_posY + ev.deltaY;             max_pos_x = Math.ceil((scale - 1) * el.clientWidth / 2);             max_pos_y = Math.ceil((scale - 1) * el.clientHeight / 2);             if (posX > max_pos_x) {                 posX = max_pos_x;             }             if (posX < -max_pos_x) {                 posX = -max_pos_x;             }             if (posY > max_pos_y) {                 posY = max_pos_y;             }             if (posY < -max_pos_y) {                 posY = -max_pos_y;             }         }           //pinch         if (ev.type == "pinch") {             scale = Math.max(.999, Math.min(last_scale * (ev.scale), 4));         }         if(ev.type == "pinchend"){last_scale = scale;}          //panend         if(ev.type == "panend"){             last_posX = posX < max_pos_x ? posX : max_pos_x;             last_posY = posY < max_pos_y ? posY : max_pos_y;         }          if (scale != 1) {             transform =                 "translate3d(" + posX + "px," + posY + "px, 0) " +                 "scale3d(" + scale + ", " + scale + ", 1)";         }          if (transform) {             el.style.webkitTransform = transform;         }     }); } 

To implement just call it with hammerIt(document.getElementById("imagid")); after the element has loaded. You can call this on as many elements as you like.

Cheers!

like image 172
K'shin Gendron Avatar answered Oct 23 '22 16:10

K'shin Gendron


Add variables last_posX and last_posY to account for the change in position when you have translated. update them on dragend so that next time a drag event is captured it takes into account where the last drag ended

var posX=0, posY=0,     scale=1, last_scale,     last_posX=0, last_posY=0,     max_pos_x=0, max_pos_y=0;  hammertime.on('touch drag transform dragend', function(ev) {     switch(ev.type) {         case 'touch':             last_scale = scale;             break;          case 'drag':             if(scale != 1){                     posX = last_posX + ev.gesture.deltaX;                     posY = last_posY + ev.gesture.deltaY;                     if(posX > max_pos_x){                         posX = max_pos_x;                     }                     if(posX < -max_pos_x){                         posX = -max_pos_x;                     }                     if(posY > max_pos_y){                         posY = max_pos_y;                     }                     if(posY < -max_pos_y){                         posY = -max_pos_y;                     }             }else{                 posX = 0;                 posY = 0;                 saved_posX = 0;                 saved_posY = 0;             }             break;          case 'transform':             scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10));             max_pos_x = Math.ceil((scale - 1) * rect.clientWidth / 2);             max_pos_y = Math.ceil((scale - 1) * rect.clientHeight / 2);             if(posX > max_pos_x){                 posX = max_pos_x;             }             if(posX < -max_pos_x){                 posX = -max_pos_x;             }             if(posY > max_pos_y){                 posY = max_pos_y;             }             if(posY < -max_pos_y){                 posY = -max_pos_y;             }             break;         case 'dragend':             last_posX = posX < max_pos_x ? posX: max_pos_x;             last_posY = posY < max_pos_y ? posY: max_pos_y;             break;     }      // transform!     var transform =             "translate3d(0, 0, 0) " +             "scale3d(1, 1, 0) ";      if(scale != 1){         transform =             "translate3d("+posX+"px,"+posY+"px, 0) " +             "scale3d("+scale+","+scale+", 0) ";     }      rect.style.transform = transform;     rect.style.oTransform = transform;     rect.style.msTransform = transform;     rect.style.mozTransform = transform;     rect.style.webkitTransform = transform; }); 
like image 24
DGS Avatar answered Oct 23 '22 17:10

DGS