iOS和Android中滚动页面的触摸事件偏移不正确

Incorrect Touch Event Offsets for Scrolled Page in iOS and Android

本文关键字:事件 触摸 不正确 Android 滚动 iOS      更新时间:2023-09-26

我们有一个网页,其中包含一些允许用户绘制的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>

第二个div/画布(顶部:915px)最初是不可见的,但可以滚动到上面并在上面涂上墨水

绘图是非常直接的代码,适用于桌面浏览器(使用适当的鼠标事件)。对于iPad,我们需要使用触摸事件来确定要绘制的点位置:

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

(其中canvasLeft和canvasTop是画布的页面相对偏移量)。

即使在滚动到第二个div/canvas之后,一切都能正常工作。

但是,一旦在上面的代码中添加了一个外部(带有溢出: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>

事实上,它们似乎正好偏离了滚动量!根据文档,screenY属性应该考虑滚动(但可能它指的是页面滚动,而不是外部div滚动)。

触摸事件是否有不同的属性,报告相对于滚动div的x和y偏移,以便正确绘制点?

或者,是否有跟踪滚动量的方法,以便将适当的偏移应用于touchX和touchY的计算?

这是我的鼠标/触摸代码。试试看。它应该对你有用:

使用触摸事件,您可以执行以下操作:"

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

在你叫它之前。

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};
}

假设您的画布被称为"画布",这些偏移量如下:

_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;