JavaScript:触摸事件在 iPad 上起作用,但在 iPhone 上不起作用

JavaScript: Touch Events Working on iPad but not iPhone

为 iPad 和 iPhone 编写 JS 触摸事件有什么区别吗?我已经阅读了大量文档,据我所知,两者的工作方式应该相同。

我有一个拖放游戏,基本上你从龙下面抓取一枚硬币并将其拖到你的金库中。拖动适用于 iPad,但不适用于 iPhone。我想弄清楚为什么。

游戏,供参考:https://codeeverydamnday.com/projects/dragondrop/dragondrop.html

JS,删节为这个问题的相关代码(为了清楚起见,有注释):

var dragndrop = (function() {
  var myX = "";
  var myY = "";
    // The coin's starting X and Y coordinate positions
  var coin = "";
    // The coin you start touching / dragging

  function touchStart(e) {
    e.preventDefault();
      // Prevents default behavior of scrolling when you touch/drag on mobile
    var coin = e.target;
    var touch = e.touches[0];
    var moveOffsetX = coin.offsetLeft - touch.pageX;
    var moveOffsetY = coin.offsetTop - touch.pageY;
      // Defines offset between left edge of coin and where you place your finger on it
    coin.addEventListener('touchmove', function() {
      var positionX = touch.pageX+moveOffsetX;
      var positionY = touch.pageY+moveOffsetY;
        // Defines the X-Y coordinates of wherever you stop dragging
      coin.style.left = positionX + 'px';
      coin.style.top = positionY + 'px';
        // Updates the coin's X-Y coordinates with the new positions
    }, false)
  }
  document.querySelector('body').addEventListener('touchstart', touchStart, false);
})();

如果有帮助,我每次在 Chrome Dev Tools 模拟器中点击/点击 iPad 屏幕时都会收到此控制台日志错误:

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.

这个错误似乎并没有阻止拖动在 iPad 上工作,但我不确定它是否与拖动在移动设备上不起作用有关?我尝试根据我看到的其他 Stack Overflow 问题添加一些东西来修复错误(例如,在我的 CSS 中添加 touch-action: none;,但错误仍然存​​在)。

有人看到我的代码有什么问题吗?我很想让这款游戏可以在手机上玩,因为大多数人都会通过这种方式访问​​它!

对于 touch-starttouch-move 事件,passive 选项的默认值设置为 true,它为真意味着您的函数不会调用 preventDefault禁用滚动。

只需将 passive 值设置为 false 即可解决您的问题。

var dragndrop = (function() {
  var myX;
  var myY;
  var coin;

  function touchStart(e) {
    e.preventDefault();

    coin = e.target;
    const touch = e.touches[0];
    const moveOffsetX = whichArt.offsetLeft - touch.pageX;
    const moveOffsetY = whichArt.offsetTop - touch.pageY;

    coin.addEventListener("touchmove", touchMove, { passive: false });

    function touchMove(e) {
      const touch = e.touches[0];
      const positionX = touch.pageX + moveOffsetX;
      const positionY = touch.pageY + moveOffsetY;

      coin.style.left = `${positionX}px`;
      coin.style.top = `${positionY}px`;
    }
  }

  document.body.addEventListener('touchstart', touchStart, { passive: false });
})();

编辑


我查看了您链接的网站上的代码,我意识到硬币没有被拖动的原因之一是因为我们正在使用 touch 以及 once 选项我传给了touchmove活动

每当使用touchmove事件时,我们必须使用新的触摸来获取屏幕上的pageXpageY位置,我决定为touchmove 事件,因为每当调用 touchstart 函数时,由于匿名函数处理程序,都会注册一个新的 touchmove 事件。

因此为其创建和命名函数将防止添加相同的函数。