简体   繁体   English

iOS和Android中滚动页面的错误触摸事件偏移

[英]Incorrect Touch Event Offsets for Scrolled Page in iOS and Android

We have a web page that contains a few div/canvas tags allowing the user to draw: 我们有一个网页,其中包含一些div / canvas标签,允许用户绘制:

 <div id="Drawing" class="FormField" style="position: absolute; top: 444px; left: 121px;
      width: 302px; height: 185px; font-size: 10pt;">
      <canvas id="DrawingCanvas" class="InkFormField" width="302" height="185" style=""></canvas>
 </div>
 <div id="Picture" class="FormField" style="position: absolute; top: 915px; left: 121px;
      width: 302px; height: 167px; font-size: 10pt;">
      <canvas id="PictureCanvas" class="InkFormField" width="302" height="167" style=""></canvas>
 </div>

The second div/canvas (with top: 915px) is initially not visible but can be scrolled to and inked on. 最初不可见第二个div / canvas(顶部:915px),但可以滚动到它并上墨。

The drawing is pretty straight-forward code which works correctly for desktop browsers (using the appropriate mouse events). 该图形是非常简单的代码,适用于桌面浏览器 (使用适当的鼠标事件)。 For the iPad we need to use touch events to determine the point locations to draw: 对于iPad,我们需要使用触摸事件来确定绘制点的位置:

        var touchX = e.changedTouches[0].screenX - canvasLeft;
        var touchY = e.changedTouches[0].screenY - canvasTop;

(where canvasLeft and canvasTop are the page-relative offsets of the canvas). (其中canvasLeft和canvasTop是画布的页面相对偏移量)。

Everything works correctly, even after scrolling to the second div/canvas. 即使滚动到第二个div / canvas,一切都可以正常工作。

However, once an outer is added to the above code (with overflow: auto ) the touchX and touchY values are no longer correct after the div is scrolled : 但是, 一旦将外部添加到上述代码中(带有溢出:auto ), 则在div滚动后, touchX和touchY 值不再正确

  <div style="overflow: auto">
     <div id="Drawing" class="FormField" style="position: absolute; top: 444px; left: 121px;
          width: 302px; height: 185px; font-size: 10pt;">
          <canvas id="DrawingCanvas" class="InkFormField" width="302" height="185" style=""></canvas>
     </div>
     <div id="Picture" class="FormField" style="position: absolute; top: 915px; left: 121px;
          width: 302px; height: 167px; font-size: 10pt;">
          <canvas id="PictureCanvas" class="InkFormField" width="302" height="167" style=""></canvas>
     </div>
  </div>

As a matter of fact they seem to be off by exactly the scrolled amount! 事实上,它们似乎完全偏离了滚动量! According to the documentation, the screenY property should take scrolling into account (but maybe it is referring to the page scrolling, not the outer div scrolling). 根据文档,screenY属性应考虑滚动(但它可能是指页面滚动,而不是外部div滚动)。

Is there a different property of the touch event that reports the x and y offsets relative to the scrolled div so that points can be drawn correctly? 触摸事件是否有其他属性来报告相对于滚动div的x和y偏移,以便可以正确绘制点?

Alternatively, is there a way to keep track of the amount of scrolling so an appropriate offset can be applied to the computation of touchX and touchY? 或者,是否有办法跟踪滚动量,以便可以将适当的偏移量应用于touchX和touchY的计算?

Here's my mouse/touch code. 这是我的鼠标/触摸代码。 Give it a try. 试试看。 It should work for you: 它应该为您工作:

With touch events you can do something like:' 通过触摸事件,您可以执行以下操作:'

if (e.targetTouches) e = e.targetTouches[0];

before you call it. 在您打电话之前。

function getMouse(e, canvas) {
  var element = canvas, offsetX = 0, offsetY = 0, mx, my;

  // Compute the total offset
  if (element.offsetParent !== undefined) {
    do {
      offsetX += element.offsetLeft;
      offsetY += element.offsetTop;
    } while ((element = element.offsetParent));
  }

  // Add padding and border style widths to offset
  // Also add the <html> offsets in case there's a position:fixed bar
  offsetX += _stylePaddingLeft + _styleBorderLeft + _htmlLeft;
  offsetY += _stylePaddingTop + _styleBorderTop + _htmlTop;

  mx = e.pageX - offsetX;
  my = e.pageY - offsetY;

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

Those offsets are as following, assuming your canvas is called "canvas": 这些偏移量如下所示,假设您的画布被称为“画布”:

_stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10)      || 0;
_stylePaddingTop  = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10)       || 0;
_styleBorderLeft  = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10)  || 0;
_styleBorderTop   = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10)   || 0;
// <html> can have a margin (typically seen with position:fixed bars)
var html = document.body.parentNode;
_htmlTop = html.offsetTop;
_htmlLeft = html.offsetLeft;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM