javascript - 在移动设备上使用 hammer.js 拖动元素失败

标签 javascript hammer.js

我正在开发一个允许用户使用 hammer.js 在屏幕上拖动对象的界面。在桌面浏览器中它可以工作,但在移动设备上,当我开始拖动时它会短暂工作,然后突然就像事件的客户端坐标突然变为 0,0 一样。

我有一个要拖动的简单 SVG 圆圈:

<svg version="1.1" viewBox="0 0 640 480" id="svg" style="width: 640px; height: 480px; top:0px; left: 0px; position: absolute;">
  <circle class="selhan" cx="320" cy="240" r="200" id="circ" 
   style="fill: none; stroke: rgb(0, 0, 0); pointer-events: all; 
   touch-action: none; user-select: none; -webkit-user-drag: none; 
   -webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
  </circle>
</svg>

我正在设置一个简单的 pan 处理程序:

var circ = document.getElementById("circ")
var Hn1=new Hammer(circ, {/*domEvents:true*/})
Hn1.add( new Hammer.Pan({ direction: Hammer.DIRECTION_ALL, threshold: 0, pointers:1 }) )
var X0,Y0
Hn1.on("panstart", function(e) {
    var ob = e.target
    var cx = ob.getAttribute("cx")
    var cy = ob.getAttribute("cy")
    X0=e.center.x-cx
    Y0=e.center.y-cy
})

Hn1.on("pan", function(e) {
        var ob = e.target
        var X = e.center.x-X0
        var Y = e.center.y-Y0
        ob.setAttribute("cx",X)
        ob.setAttribute("cy",Y)    
})

我创建了一个 Fiddle展示。在移动设备上,如果我将手指放在圆圈的中心并非常缓慢地移动,我会在短时间内看到圆圈轨道,但突然中心跳到 0,0,而在桌面上它会跟随指针移动一天。

我创建了一个 Updated Fiddlepanstartpancancelpanend 事件发生时显示。我看到的是,当圆跳到原点时,我收到了一个 pancancel 事件。为什么即使我的手指还没有从屏幕上移开,我的平移功能还是被取消了?

更奇怪的是 this version .我所做的只是颠倒跨度的顺序(显示 panstartpancancelpanend 发生次数的计数器)。如果 span SVG 之后,那么我突然可以平移圆圈,但只能水平移动。但是,如果跨度之前出现或不出现,则平移会在短时间的手指移动后突然取消。 好吧,结果是滚动的是元素,而不是圆圈.然而,41 版在桌面上的表现也很奇怪......当我第一次尝试时,我根本无法让它响应鼠标事件,但后来它开始工作,然后又停止了,所有这些都是通过简单地更改为不同的版本和返回。

更新:为了深入了解调用 pancancel 回调的原因,我检测了我的 hammer.js 副本。 . PanRecognizer directionTest 函数(第 1778 行)返回 false,导致生成取消。发生的事情总是某种形式的“什么都没发生”,导致 hasMoved 为假,或者距离为 0(我尝试将阈值设置为 -1,但这只是移动到问题出现的地方),或者方向为 DIRECTION_NONE。

这仍然没有多大意义 - 即使我以足够快的速度平移以至于我永远不会在两个事件之间获得零移动,我也看到这种情况发生,即使我平移缓慢我也不会'不要期望这会成为问题。

更新 2: 我添加了以下工具:

    Hn1.on("hammer.input",function(ev) {
        console.log("debug",ev)
    })

当我这样做时,我看到一个源事件 pointercancel这表明浏览器正在取消实际使用中的指针运动。在审查documentation对于此事件,提到的取消指针事件的四个原因均不适用于这种情况。这是怎么回事?!

最佳答案

迈克尔,我遇到了和你一样的问题。我已经提交了 bug report在 GitHub 上,带有示例和视频。很高兴看到您发现它与浏览器触发的“pointercancel”有关,但到目前为止它还没有帮助我弄清楚如何解决这个问题。你在这件事上有什么进展吗?

作为引用,这个StackOverflow thread谈论同样的问题。不幸的是,到目前为止,对于 HammerJS,没有任何修复对我有用。

编辑: 事实证明,阻止窗口上默认的“touchmove”事件处理将解决页面上任何 SVG 元素的这个问题。这是个好消息,但它也禁用了页面上的所有滚动行为。相反,我所做的是捕获 SVG 对象上的“touchmove”事件,因此其中的任何后代都将正确平移。我还不确定它是否有任何不良副作用,但到目前为止,这意味着我在 SVG 中的平移终于可以在 Android 浏览器上运行了!

为了完整起见,这里是必要的代码:

const options = { passive: false }; // needed because Chrome has this set to "true" by default for "touchmove" events
    mySVG.addEventListener(
      "touchmove",
      e => e.preventDefault(),
      options
    );

关于javascript - 在移动设备上使用 hammer.js 拖动元素失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48876527/

相关文章:

javascript - 如何在 CouchDB 的显示函数中遍历所有文档?

javascript - 在桌面浏览器上使用 Hammer.js 有什么缺点吗?

javascript - 使用require js加载锤子

javascript - 为什么我的 Java Quicksort 没有移植到 Javascript 中?

javascript - 如何在html中绘制图像上元素的x,y坐标

javascript - 无法更改 Material-UI OutlinedInput 的边框颜色

javascript - Hammer.js 中的捏合事件触发平移事件

java - 用于将 Rhino 与 Java 结合使用(通过脚本框架)的有用的小型支持工具包?

Angular/HammerJS - 避免在捏合/捏合时旋转手势

jquery - 如何让 Hammer JS 与 Backbone 一起工作