在浏览器中捕捉缩放

Posted

技术标签:

【中文标题】在浏览器中捕捉缩放【英文标题】:Catch pinch-zoom in browser 【发布时间】:2019-07-29 05:58:18 【问题描述】:

我有一个 Web 应用程序,它基本上是一个可以在上面绘制的画布。我正在处理绘图 - 通过鼠标或单指触摸 - 它运行良好。

画布比屏幕大,我需要实现自己的缩放机制(因为我只想缩放画布,而不是整个屏幕)。我为wheel 事件添加了一个处理程序,并且我正确处理了Control-Wheels。现在我需要处理捏缩放。

我的画布作为track-action: pinch-zoom CSS 设置。这使两个手指滑动即可滚动,这非常好。我也想让浏览器处理捏缩放,但我想自己处理缩放逻辑(就像我使用鼠标滚轮一样)。

有什么方法可以捕捉到捏缩放事件并覆盖缩放行为?

我在 android 上使用 Chrome,但这项技术应该也适用于 ios 上的 Safari。

【问题讨论】:

我已经为画布实现了一个带有点缩放的双指捏合缩放算法,但我使用的是touch-action: manipulation。如果您可以使用该 CSS 设置生存,我可以发布一些代码。 不,我不能,我不能拥有pan-xpan-y 我想做相反的事情——让浏览器处理单个元素的缩放行为。你是在暗示有办法做到这一点吗? 【参考方案1】:

顺便说一句,好主意。 我在codepen 上发现了一些值得你花时间的东西。我也将它剥离了一点,并在下面插入为 sn-p。让我知道它是否对您有帮助。 另外如果你想使用库,你可以尝试hammer.js 或jgestures 进行捏缩放手势。

  var image_x = 0, image_y = 0;
  var zoom = 0.5;
  var mouse_x = 0, mouse_y = 0, finger_dist = 0;
  var source_image_obj = new Image();
  source_image_obj.addEventListener('load', function () 
    reset_settings();
  , false); // Reset (x,y,zoom) when new image loads

  function load_url() 
    source_image_obj.src = document.getElementById("theurl").value; // load the image
  

  function update_canvas() 
    var mainCanvas = document.getElementById("mainCanvas");
    var mainCanvasCTX = document.getElementById("mainCanvas").getContext("2d");
    var canvas_w = mainCanvas.width, canvas_h = mainCanvas.height; // make things easier to read below
    // Keep picture in bounds
    if (image_x - (canvas_w * zoom / 2) > source_image_obj.width) image_x = source_image_obj.width + (canvas_w * zoom / 2);
    if (image_y - (canvas_h * zoom / 2) > source_image_obj.height) image_y = source_image_obj.height + (canvas_h * zoom / 2);
    if (image_x + (canvas_w * zoom / 2) < 0) image_x = 0 - (canvas_w * zoom / 2);
    if (image_y + (canvas_h * zoom / 2) < 0) image_y = 0 - (canvas_h * zoom / 2);
    // Draw the scaled image onto the canvas
    mainCanvasCTX.clearRect(0, 0, canvas_w, canvas_h);
    mainCanvasCTX.drawImage(source_image_obj, image_x - (canvas_w * zoom / 2), image_y - (canvas_h * zoom / 2), canvas_w * zoom, canvas_h * zoom, 0, 0, canvas_w, canvas_h);
  

  function reset_settings() 
    image_x = source_image_obj.width / 2;
    image_y = source_image_obj.height / 2;
    zoom = 1;
    update_canvas(); // Draw the image in its new position
  

  document.addEventListener('wheel', function (e) 
    if (e.deltaY < 0) 
      zoom = zoom * 1.5;
     else 
      zoom = zoom / 1.5;
    
    update_canvas();
  , false);

  document.addEventListener('mousemove', function (e) 
    if (e.buttons > 0) 
      window.getSelection().empty();
      image_x = image_x + zoom * (mouse_x - e.clientX);
      image_y = image_y + zoom * (mouse_y - e.clientY);
    
    mouse_x = e.clientX;
    mouse_y = e.clientY; // Save for next time
    update_canvas(); // draw the image in its new position
  , false);

  function get_distance(e) 
    var diffX = e.touches[0].clientX - e.touches[1].clientX;
    var diffY = e.touches[0].clientY - e.touches[1].clientY;
    return Math.sqrt(diffX * diffX + diffY * diffY); // Pythagorean theorem
  

  document.addEventListener('touchstart', function (e) 
    if (e.touches.length > 1)  // if multiple touches (pinch zooming)
      finger_dist = get_distance(e); // Save current finger distance
     // Else just moving around
    mouse_x = e.touches[0].clientX; // Save finger position
    mouse_y = e.touches[0].clientY; //
  , false);

  document.addEventListener('touchmove', function (e) 
    e.preventDefault(); // Stop the window from moving
    if (e.touches.length > 1)  // If pinch-zooming
      var new_finger_dist = get_distance(e); // Get current distance between fingers
      zoom = zoom * Math.abs(finger_dist / new_finger_dist); // Zoom is proportional to change
      finger_dist = new_finger_dist; // Save current distance for next time
     else  // Else just moving around
      image_x = image_x + (zoom * (mouse_x - e.touches[0].clientX)); // Move the image
      image_y = image_y + (zoom * (mouse_y - e.touches[0].clientY)); //
      mouse_x = e.touches[0].clientX; // Save finger position for next time
      mouse_y = e.touches[0].clientY; //
    
    update_canvas(); // draw the new position
  , false);

  document.addEventListener('touchend', function (e) 
    mouse_x = e.touches[0].clientX;
    mouse_y = e.touches[0].clientY; // could be down to 1 finger, back to moving image
  , false);
    * 
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    
    canvas 
      background: #e74c3c;
      border: 4px solid black;
    
    .box-photo 
      border: 1px dashed black;
    
    .box-photo img 
      width: 100%;
    
<html>
<head>
  <meta charset="utf-8" />
<body onload="load_url();">
  <div class="box">
    <div class="box-photo">
      <canvas id="mainCanvas"  >
        <input id="theurl" value="https://mlb-s1-p.mlstatic.com/relogio-mondaine-classico-78527-original-a-prova-dagua-202101-MLB20273713546_042015-F.jpg">
        Your browser does not support the HTML5 canvas tag.
      </canvas>
    </div>
  </div>
</body>
</html>

【讨论】:

以上是关于在浏览器中捕捉缩放的主要内容,如果未能解决你的问题,请参考以下文章

当您尝试放大时,CSS 滚动捕捉卡住

如何使用 UIScrollView 捕捉缩放?

Autodesk Forge Viewer PDF 捕捉和缩放问题

如何关闭win10ie浏览器的双指缩放功能

CSS 滚动捕捉延迟多长时间?

在移动浏览器上缩放或滚动