我正在使用一个界面来允许用户使用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 Fiddle,会在panstart
,pancancel
和panend
事件发生时显示。我所看到的是,当圆圈跳到原点时,我得到pancancel
事件。为什么我的平底锅被取消了,即使我还没有从屏幕上抬起手指?
更奇怪的是this version。我所做的只是颠倒了跨度的顺序(显示了好的,原来它是元素那个滚动,而不是圆圈。然而,版本41在桌面上也表现得很奇怪...当我第一次尝试它时,我根本无法响应鼠标事件,但它开始工作,然后再次停止,所有这一切都只需更改到不同的版本和返回。panstart
,pancancel
和panend
发生了多少次的计数器。如果跨度在 SVG之后,那么突然我可以平移圆圈,但仅水平。但是如果跨度之前或者那里没有,那么在少量手指移动之后平移就会突然取消。
更新:为了了解调用pancancel
回调的原因,我检查了hammer.js的副本。 PanRecognizer directionTest
函数(第1778行)返回false,导致生成取消。发生的事情总是某种形式的&#34;什么都没发生&#34;,导致hasMoved
为假,或者距离为0(我尝试将阈值设置为-1,但这只是在问题出现的地方移动了) ,或方向为DIRECTION_NONE。
这仍然没有多大意义 - 即使我以足够快的速度进行平移,我也不会在两个事件之间获得零移动,即使我正在平移慢慢地我不希望这是一个问题。
更新2: 我添加了以下仪器:
Hn1.on("hammer.input",function(ev) {
console.log("debug",ev)
})
当我这样做时,我看到一个源事件pointercancel
,它表明浏览器正在取消实际使用中间的指针运动。在查看此事件的documentation时,在这种情况下,指针事件被取消的四个原因都不适用。这是怎么回事?!
答案 0 :(得分:0)
答案 1 :(得分:0)
作为参考,这个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
);