【问题标题】:JavaScript: Touch Events Working on iPad but not iPhoneJavaScript:在 iPad 但不是 iPhone 上工作的触摸事件
【发布时间】:2021-05-21 19:45:34
【问题描述】:

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

我有一个拖放游戏,基本上你从龙的下方抓起一枚硬币并将其拖到你的金库中。拖动适用于 iPad,但不适用于 iPhone。我正在尝试找出原因。

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

JS,只删减了这个问题的相关代码(为了清楚起见,用 cmets):

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 开发工具模拟器中单击/点击 iPad 屏幕时都会收到此控制台日志错误:

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

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

有人看到我的代码有什么问题吗?我希望这款游戏可以在移动设备上玩,因为这是大多数人访问它的方式!

【问题讨论】:

    标签: javascript ios events drag-and-drop touch


    【解决方案1】:

    对于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,还因为我传递给@987654330 的once 选项@事件。

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

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

    【讨论】:

    • 修复了我的控制台日志错误;谢谢!我已经在我的代码中的这两个地方添加了“被动:假”属性,一旦新代码清除缓存,我将在几个小时内在我的手机上进行测试。如果可行,我会将您的答案标记为答案!如果没有别的,它至少修复了控制台日志错误。
    • 好吧,控制台日志错误已修复,但现在点击和拖动在 iPad 或移动设备上根本不起作用(点击/点击过去可以工作,而不是拖动)。我将查看我的其余代码,看看我在描述中粘贴的内容之外的内容是否会影响功能。
    • @KatieReynolds 我对答案进行了编辑。
    • 谢谢!我会尝试编辑并让你知道它是如何进行的:)
    • 成功了!!!我连续 3 天一直在解决这个问题,您的代码更新终于帮助了我。非常感谢! :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-01-22
    • 1970-01-01
    • 2016-10-17
    • 2011-08-24
    • 2017-05-15
    • 2011-03-29
    • 1970-01-01
    相关资源
    最近更新 更多