【问题标题】:Touch events on canvas in javascript have wrong coordinatesjavascript中画布上的触摸事件坐标错误
【发布时间】:2018-01-16 10:44:44
【问题描述】:

我有一个使用键盘的桌面浏览器的 html5 画布游戏,我正在尝试通过添加触摸屏控件来创建与智能手机的兼容性。

当前的问题是触摸输入的事件返回的 X 和 Y 坐标与我触摸的位置不匹配。

上图中的紫色圆点是我添加的诊断测试。游戏在检测到触摸事件的每个位置放置一个圆圈。在这种情况下,我追踪了手机屏幕的边框。点的位置说明了我的屏幕实际位置与游戏认为的位置之间的差异。

<body onload="html_init()">
  <div class="canvas_div" id="canvas_div">
    <canvas width="1050" height="600" id="canvas"></canvas>
  </div>
</body>

function html_init()
  {
  canvas_html = document.getElementById ("canvas");
  window.addEventListener ("resize", resize_canvas, false);
  canvas_html.addEventListener ("touchstart",  function(event) {touch_start (event)},  false);
  }

function resize_canvas ()
  {
  // Scale to fit window, decide which scaling reaches edge first.

  canvas_2d.restore();
  canvas_2d.save();

  var game_ratio = canvas_2d.canvas.width / canvas_2d.canvas.height;
  var window_ratio = window.innerWidth / window.innerHeight;
  var xratio = window.innerWidth / canvas_2d.canvas.width;
  var yratio = window.innerHeight / canvas_2d.canvas.height;

  var ratio;
  if (game_ratio > window_ratio) ratio = xratio;
  else ratio = yratio;
  if (ratio > 1) ratio = 1;

  canvas_2d.scale (ratio, ratio);
  }

function touch_start (event)
  {
  var touch = event.changedTouches;
  var x = touch[0].pageX;
  var y = touch[0].pageY;

  // this goes on to add the purple test sprite to the screen at that location.
  }

我尝试过引用 pageX、clientX 和 screenX,但它们都没有正确的值。尽管我的画布设置为 1050 x 600,这是我的游戏运行时的分辨率,但触摸屏似乎认为它在 650 x 350 左右。如果重要的话,测试手机是 iPhone 6。

我现在不确定要检查什么。任何想法都表示赞赏。

更新:我已将问题缩小到两个事实 - 画布大小大于正在显示的网页的显示区域,并且我正在使用 resize_canvas()设置比例。看来我将不得不减小画布的整体尺寸以适应手机,或者根据比例对坐标进行公式调整。

【问题讨论】:

  • 请粘贴 HTML。画布通常采用描述其大小的高度和宽度属性。你能检查一下你那里没有提供错误的值吗?
  • @MartinChaov:我已经粘贴了我的 html。那里的一切对我来说都是正确的。
  • 在触摸事件中使用this
  • @K3N:这是个好主意,但我的画布始终位于 (0, 0)。我使用了绝对定位。
  • @NightmareGames 它还涵盖了缩放的画布

标签: javascript event-handling html5-canvas touchscreen


【解决方案1】:
canvas_html.addEventListener ("touchstart", touch_start,  false);

function resize_canvas ()
  {
  // Scale to fit window, decide which scaling reaches edge first.

  canvas_2d.restore();
  canvas_2d.save();

  var current_ratio = canvas_2d.canvas.width / canvas_2d.canvas.height;
  var new_ratio = window.innerWidth / window.innerHeight;
  var xratio = window.innerWidth / canvas_2d.canvas.width;
  var yratio = window.innerHeight / canvas_2d.canvas.height;

  if (current_ratio > new_ratio) screen_size_ratio = xratio;
  else screen_size_ratio = yratio;
  if (screen_size_ratio > 1) screen_size_ratio = 1;

  canvas_2d.scale (screen_size_ratio, screen_size_ratio);
  }

function touch_start (event)
  {
  var touch = event.changedTouches;
  var x = Math.floor (touch[0].clientX / screen_size_ratio);
  var y = Math.floor (touch[0].clientY / screen_size_ratio);
  }

由于我在画布上进行了 scale(),因此必须使用我在 canvas_resize() 中计算的比率对实际坐标进行非缩放。

我还必须将“touchstart”事件处理程序更改为不使用匿名函数。无论出于何种原因,这都会导致手机浏览器默认使用“mousedown”进行点击。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多