2013-10-29 155 views
2

我想捏缩放功能的图像。我想让它放大手指所在的区域。捏与Hammer.js缩放

我的指数只有

<div id="wrapper" style="-webkit-transform: translate3d(0,0,0);overflow: hidden;"> 

</div> 

我的缩放和滚动脚本是类似with this example。我已经做了一些改动,以配合我的项目

我的问题是在

 case 'transform': 
      rotation = last_rotation + ev.gesture.rotation; 
      scale = Math.max(1, Math.min(last_scale * ev.gesture.scale, 10)); 
      break; 

我怎样才能改变它,使其不放大到图片的中心,但在地方第一手指触摸显示器?

对不起,我的英语不好:)

回答

4

这是hammer.js和tap的例子。当你点击它时会放大你点击的点。事件数据对于所有手势都是常见的,所以从点击切换到缩放应该可以工作。这是一个很好的例子。你可能需要增加缩放步骤,因为你捏。它已经在Chrome(v30)和firefox(v24)上测试过。 它是基于线程 Zoom in on a point (using scale and translate) 提到的解决方案,因为您会看到替代方案也可以使用画布。

HTML

<div style="-webkit-transform: translate3d(0,0,0);overflow: hidden;" class="zoomable"> 
    <img src="http://i.telegraph.co.uk/multimedia/archive/01842/landscape-rainbow_1842437i.jpg" /> 
</div> 

JS

(function ($) { 

    $(document).ready(function() { 


     var scale = 1; // scale of the image 
     var xLast = 0; // last x location on the screen 
     var yLast = 0; // last y location on the screen 
     var xImage = 0; // last x location on the image 
     var yImage = 0; // last y location on the image 

     Hammer($('.zoomable img').get(0)).on("tap", function (event) { 

      var posX = event.gesture.center.pageX; 
      var posY = event.gesture.center.pageY; 


      // find current location on screen 
      var xScreen = posX; //- $(this).offset().left; 
      var yScreen = posY; //- $(this).offset().top; 

      // find current location on the image at the current scale 
      xImage = xImage + ((xScreen - xLast)/scale); 
      yImage = yImage + ((yScreen - yLast)/scale); 

      scale++; 

      // determine the location on the screen at the new scale 
      var xNew = (xScreen - xImage)/scale; 
      var yNew = (yScreen - yImage)/scale; 

      // save the current screen location 
      xLast = xScreen; 
      yLast = yScreen; 

      // redraw 
      $(this).css('-webkit-transform', 'scale(' + scale + ')' + 'translate(' + xNew + 'px, ' + yNew + 'px' + ')') 
       .css('-webkit-transform-origin', xImage + 'px ' + yImage + 'px').css('-moz-transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)').css('-moz-transform-origin', xImage + 'px ' + yImage + 'px') 
       .css('-o-transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)').css('-o-transform-origin', xImage + 'px ' + yImage + 'px').css('transform', 'scale(' + scale + ') translate(' + xNew + 'px, ' + yNew + 'px)'); 
     }); 
    }); 
})(jQuery); 

http://jsfiddle.net/SySZL/

+0

会尝试明天!看起来不错,这给我一点提示,我如何得到页面的当前位置。 我会在测试后报告它是否适用:) – Nordiii

+0

@ user2664120您从event.gesture.center.pageX和event.gesture.center.pageY获得的当前捏合位置。缩放位置取决于缩放位置以及图像缩放的程度。这就是答案的代码,在锤子敲击回调函数中。 – melc

+0

嗨,感谢您将代码稍微更改为符合我当前的代码与您的示例我得到它的工作非常感谢! – Nordiii

-1

退房的Pinch Zoom and Pan with HammerJS demo。此示例已在Android,iOS和Windows Phone上进行了测试。

您可以在Pinch Zoom and Pan with HammerJS找到源代码。

为方便起见,这里是源代码:

<!DOCTYPE html> 
 
<html> 
 
<head> 
 
    <meta charset="utf-8"> 
 
    <meta name="viewport" 
 
     content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1"> 
 
    <title>Pinch Zoom</title> 
 
</head> 
 

 
<body> 
 

 
    <div> 
 

 
    <div style="height:150px;background-color:#eeeeee"> 
 
     Ignore this area. Space is needed to test on the iPhone simulator as pinch simulation on the 
 
     iPhone simulator requires the target to be near the middle of the screen and we only respect 
 
     touch events in the image area. This space is not needed in production. 
 
    </div> 
 

 
    <style> 
 

 
     .pinch-zoom-container { 
 
     overflow: hidden; 
 
     height: 300px; 
 
     } 
 

 
     .pinch-zoom-image { 
 
     width: 100%; 
 
     } 
 

 
    </style> 
 

 
    <script src="https://hammerjs.github.io/dist/hammer.js"></script> 
 

 
    <script> 
 

 
     var MIN_SCALE = 1; // 1=scaling when first loaded 
 
     var MAX_SCALE = 64; 
 

 
     // HammerJS fires "pinch" and "pan" events that are cumulative in nature and not 
 
     // deltas. Therefore, we need to store the "last" values of scale, x and y so that we can 
 
     // adjust the UI accordingly. It isn't until the "pinchend" and "panend" events are received 
 
     // that we can set the "last" values. 
 

 
     // Our "raw" coordinates are not scaled. This allows us to only have to modify our stored 
 
     // coordinates when the UI is updated. It also simplifies our calculations as these 
 
     // coordinates are without respect to the current scale. 
 

 
     var imgWidth = null; 
 
     var imgHeight = null; 
 
     var viewportWidth = null; 
 
     var viewportHeight = null; 
 
     var scale = null; 
 
     var lastScale = null; 
 
     var container = null; 
 
     var img = null; 
 
     var x = 0; 
 
     var lastX = 0; 
 
     var y = 0; 
 
     var lastY = 0; 
 
     var pinchCenter = null; 
 

 
     // We need to disable the following event handlers so that the browser doesn't try to 
 
     // automatically handle our image drag gestures. 
 
     var disableImgEventHandlers = function() { 
 
     var events = ['onclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover', 
 
         'onmouseup', 'ondblclick', 'onfocus', 'onblur']; 
 

 
     events.forEach(function (event) { 
 
      img[event] = function() { 
 
      return false; 
 
      }; 
 
     }); 
 
     }; 
 

 
     // Traverse the DOM to calculate the absolute position of an element 
 
     var absolutePosition = function (el) { 
 
     var x = 0, 
 
      y = 0; 
 

 
     while (el !== null) { 
 
      x += el.offsetLeft; 
 
      y += el.offsetTop; 
 
      el = el.offsetParent; 
 
     } 
 

 
     return { x: x, y: y }; 
 
     }; 
 

 
     var restrictScale = function (scale) { 
 
     if (scale < MIN_SCALE) { 
 
      scale = MIN_SCALE; 
 
     } else if (scale > MAX_SCALE) { 
 
      scale = MAX_SCALE; 
 
     } 
 
     return scale; 
 
     }; 
 

 
     var restrictRawPos = function (pos, viewportDim, imgDim) { 
 
     if (pos < viewportDim/scale - imgDim) { // too far left/up? 
 
      pos = viewportDim/scale - imgDim; 
 
     } else if (pos > 0) { // too far right/down? 
 
      pos = 0; 
 
     } 
 
     return pos; 
 
     }; 
 

 
     var updateLastPos = function (deltaX, deltaY) { 
 
     lastX = x; 
 
     lastY = y; 
 
     }; 
 

 
     var translate = function (deltaX, deltaY) { 
 
     // We restrict to the min of the viewport width/height or current width/height as the 
 
     // current width/height may be smaller than the viewport width/height 
 

 
     var newX = restrictRawPos(lastX + deltaX/scale, 
 
            Math.min(viewportWidth, curWidth), imgWidth); 
 
     x = newX; 
 
     img.style.marginLeft = Math.ceil(newX*scale) + 'px'; 
 

 
     var newY = restrictRawPos(lastY + deltaY/scale, 
 
            Math.min(viewportHeight, curHeight), imgHeight); 
 
     y = newY; 
 
     img.style.marginTop = Math.ceil(newY*scale) + 'px'; 
 
     }; 
 

 
     var zoom = function (scaleBy) { 
 
     scale = restrictScale(lastScale*scaleBy); 
 

 
     curWidth = imgWidth*scale; 
 
     curHeight = imgHeight*scale; 
 

 
     img.style.width = Math.ceil(curWidth) + 'px'; 
 
     img.style.height = Math.ceil(curHeight) + 'px'; 
 

 
     // Adjust margins to make sure that we aren't out of bounds 
 
     translate(0, 0); 
 
     }; 
 

 
     var rawCenter = function (e) { 
 
     var pos = absolutePosition(container); 
 

 
     // We need to account for the scroll position 
 
     var scrollLeft = window.pageXOffset ? window.pageXOffset : document.body.scrollLeft; 
 
     var scrollTop = window.pageYOffset ? window.pageYOffset : document.body.scrollTop; 
 

 
     var zoomX = -x + (e.center.x - pos.x + scrollLeft)/scale; 
 
     var zoomY = -y + (e.center.y - pos.y + scrollTop)/scale; 
 

 
     return { x: zoomX, y: zoomY }; 
 
     }; 
 

 
     var updateLastScale = function() { 
 
     lastScale = scale; 
 
     }; 
 

 
     var zoomAround = function (scaleBy, rawZoomX, rawZoomY, doNotUpdateLast) { 
 
     // Zoom 
 
     zoom(scaleBy); 
 

 
     // New raw center of viewport 
 
     var rawCenterX = -x + Math.min(viewportWidth, curWidth)/2/scale; 
 
     var rawCenterY = -y + Math.min(viewportHeight, curHeight)/2/scale; 
 

 
     // Delta 
 
     var deltaX = (rawCenterX - rawZoomX)*scale; 
 
     var deltaY = (rawCenterY - rawZoomY)*scale; 
 

 
     // Translate back to zoom center 
 
     translate(deltaX, deltaY); 
 

 
     if (!doNotUpdateLast) { 
 
      updateLastScale(); 
 
      updateLastPos(); 
 
     } 
 
     }; 
 

 
     var zoomCenter = function (scaleBy) { 
 
     // Center of viewport 
 
     var zoomX = -x + Math.min(viewportWidth, curWidth)/2/scale; 
 
     var zoomY = -y + Math.min(viewportHeight, curHeight)/2/scale; 
 

 
     zoomAround(scaleBy, zoomX, zoomY); 
 
     }; 
 

 
     var zoomIn = function() { 
 
     zoomCenter(2); 
 
     }; 
 

 
     var zoomOut = function() { 
 
     zoomCenter(1/2); 
 
     }; 
 

 
     var onLoad = function() { 
 

 
     img = document.getElementById('pinch-zoom-image-id'); 
 
     container = img.parentElement; 
 

 
     disableImgEventHandlers(); 
 

 
     imgWidth = img.width; 
 
     imgHeight = img.height; 
 
     viewportWidth = img.offsetWidth; 
 
     scale = viewportWidth/imgWidth; 
 
     lastScale = scale; 
 
     viewportHeight = img.parentElement.offsetHeight; 
 
     curWidth = imgWidth*scale; 
 
     curHeight = imgHeight*scale; 
 

 
     var hammer = new Hammer(container, { 
 
      domEvents: true 
 
     }); 
 

 
     hammer.get('pinch').set({ 
 
      enable: true 
 
     }); 
 

 
     hammer.on('pan', function (e) { 
 
      translate(e.deltaX, e.deltaY); 
 
     }); 
 

 
     hammer.on('panend', function (e) { 
 
      updateLastPos(); 
 
     }); 
 

 
     hammer.on('pinch', function (e) { 
 

 
      // We only calculate the pinch center on the first pinch event as we want the center to 
 
      // stay consistent during the entire pinch 
 
      if (pinchCenter === null) { 
 
      pinchCenter = rawCenter(e); 
 
      var offsetX = pinchCenter.x*scale - (-x*scale + Math.min(viewportWidth, curWidth)/2); 
 
      var offsetY = pinchCenter.y*scale - (-y*scale + Math.min(viewportHeight, curHeight)/2); 
 
      pinchCenterOffset = { x: offsetX, y: offsetY }; 
 
      } 
 

 
      // When the user pinch zooms, she/he expects the pinch center to remain in the same 
 
      // relative location of the screen. To achieve this, the raw zoom center is calculated by 
 
      // first storing the pinch center and the scaled offset to the current center of the 
 
      // image. The new scale is then used to calculate the zoom center. This has the effect of 
 
      // actually translating the zoom center on each pinch zoom event. 
 
      var newScale = restrictScale(scale*e.scale); 
 
      var zoomX = pinchCenter.x*newScale - pinchCenterOffset.x; 
 
      var zoomY = pinchCenter.y*newScale - pinchCenterOffset.y; 
 
      var zoomCenter = { x: zoomX/newScale, y: zoomY/newScale }; 
 

 
      zoomAround(e.scale, zoomCenter.x, zoomCenter.y, true); 
 
     }); 
 

 
     hammer.on('pinchend', function (e) { 
 
      updateLastScale(); 
 
      updateLastPos(); 
 
      pinchCenter = null; 
 
     }); 
 

 
     hammer.on('doubletap', function (e) { 
 
      var c = rawCenter(e); 
 
      zoomAround(2, c.x, c.y); 
 
     }); 
 

 
     }; 
 

 
    </script> 
 

 
    <button onclick="zoomIn()">Zoom In</button> 
 
    <button onclick="zoomOut()">Zoom Out</button> 
 

 
    <div class="pinch-zoom-container"> 
 
     <img id="pinch-zoom-image-id" class="pinch-zoom-image" onload="onLoad()" 
 
      src="https://hammerjs.github.io/assets/img/pano-1.jpg"> 
 
    </div> 
 

 

 
    </div> 
 

 
</body> 
 
</html>

+0

与本机iOS捏缩放和平移相比,这种行为是滞后和丑陋的。 –