如何通过JavaScript确定触摸事件(或鼠标事件)中的真实X、Y坐标?

3
我一直在处理触摸事件,代码运行得很好,直到画布不是从左上角开始。一旦我在它之前添加任何东西,报告的事件就会偏移画布的位置。
我通过在触摸位置周围画一个圆来确定这一点。该圆总是受到画布偏移量从屏幕左上角的影响。
查看触摸开始事件的事件,我可以看到有一个pageY可用(在chrome中使用usb调试)。但是当我搜索时,似乎它不是标准的一部分,而且似乎有些人认为它可能已经过时了(尽管我无法找到任何一种方式)。
所以我的问题是什么是最佳的跨浏览器方法来处理这个问题(主要关注safari和chrome,ie webkit,firefox是一个很好的选择)?
对于鼠标事件也存在同样的问题,我创建了一个JSFiddle of the problem。但我不确定是否对于鼠标事件和触摸事件都适用相同的属性。
我应该注意到,我知道我可以硬编码偏移量并解决问题,但是我正在寻找一种解决方案,它使用手头的信息,而不需要任何特定于我的html的硬编码代码。
为了重新创建JSFiddle,HTML、CSS和Javascript如下:
<div class="title"></div>
<div class="container">
  <canvas id="myCanvas"></canvas>
</div>

CSS:

body {
  background-color: #ff0000;
  margin: 0px;
}

canvas {
  display:block;
  position:absolute;
  width:100%;
  height:100%;
  background-color:#000;
}

.title {
  position:absolute;
  top:0px;
  left:0px;
  width: 100%;
  height: 40px;
  background-color: #888;
}

.container {
  width:auto;
  text-align:center;
  background-color:#777;
  width:100%;
  position:absolute;
  top:40px;
  left:0px;
  bottom:0px;
}

JavaScript:

var onMouseDown = function(e) {
    draw(document.getElementById('myCanvas').getContext('2d'), e.clientX, e.clientY);
}

$(function () {
    document.getElementById('myCanvas').addEventListener('mousedown', onMouseDown, false);
});


function draw(ctx, x, y) {
ctx.canvas.width = ctx.canvas.offsetWidth; 
ctx.canvas.height = ctx.canvas.offsetHeight;      

  var radius = 50;
  var lineWidth = 15;
  var r = 255;
  var g = 75;
  var b = 75;
  var a75 = 0.05;

  var adj = Math.abs(lineWidth / 2);

  rad = radius + adj;

  var stop1 = (rad - lineWidth) / rad;
  var stop2 = 0;
  var stop3 = stop1 + (1 - stop1) / 2;
  var stop4 = 0;
  var stop5 = 1;

  stop2 = stop3 - (stop3 - stop1) / 2;
  stop4 = stop3 + (stop5 - stop3) / 2;

  var radgrad = ctx.createRadialGradient(x, y, 0, x, y, rad);

  radgrad.addColorStop(stop1, 'rgba(' + r + ',' + g + ',' + b + ', 0)');
  radgrad.addColorStop(stop2, 'rgba(' + r + ',' + g + ',' + b + ', .4)');
  radgrad.addColorStop(stop3, 'rgba(' + r + ',' + g + ',' + b + ', 1)');
  radgrad.addColorStop(stop4, 'rgba(' + r + ',' + g + ',' + b + ', .4)');
  radgrad.addColorStop(stop5, 'rgba(' + r + ',' + g + ',' + b + ', 0)');

  ctx.fillStyle = radgrad;
  ctx.arc(x, y, rad, 0, 2 * Math.PI, true);
  ctx.fill();
}
2个回答

4
这应该可以正常工作:http://jsfiddle.net/DG4fb/3/ 你的画布的顶部和左侧不是 clientX == 0; clientY == 0;,所以你需要计算偏移量。你的画布的左上角在哪里?它是它的 offsetLeftoffsetTop 加上它的 offsetParent 的值和其 offsetParent.offsetParent 的值等等。这就是 recursiveOffsetLeftAndTop 函数为你处理的内容。

谢谢您,Cat Chen,那很好用。有趣的是,在鼠标按下事件中有 offsetX 和 offsetY,但出于某种奇怪的原因,它们在触摸事件中不可用,非常令人沮丧。顺便说一下,您的解决方案存在问题,它没有考虑到元素是否超出了可见屏幕范围。例如,在走马灯中,左右两侧有一些不可见的 divs。在我的示例中,它会在 X 上出现问题,但老实说,我可以忽略它,因为只有 Y 给我带来了麻烦。 :-) - Metalskin
我的代码有一个小错误。它无法计算页面滚动。请查看此处以获取正确答案:http://www.quirksmode.org/js/events_properties.html#position - Cat Chen

0
如果我们使用PageX和PageY而不是ClientX和ClientY,在我的情况下它完美地工作了...
        var offsets = recursiveOffsetLeftAndTop(canvas);
        var x = evt.targetTouches[0].pageX - offsets.offsetLeft;
        var y = evt.targetTouches[0].pageY - offsets.offsetTop;

感谢您提供的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接