如何在手指已经触摸屏幕后添加到DOM中的元素上捕获touchmove事件?

8
我正在为iPad开发一个JavaScript / html5项目。
我需要能够捕捉在触摸开始之后(即在人们把手指放在屏幕上之后),添加到DOM之前的元素上的touchmove事件。
我尝试模拟一个touchstart事件并通过编程方式触发它...
$( "#container" ).append( element );
element.on( "touchmove", doStuff );
var ev = $.Event( "touchstart" );
element.trigger( ev );

然而这种方案并不奏效。唯一让doStuff开始触发的方法是抬起手指并再次触摸屏幕,从而触发第二次touchstart事件。

如何在手指已经在屏幕上的情况下捕获添加到DOM中的元素上的touchmove事件?


能否在 http://jsfiddle.net 上创建这个问题的简化版本?我对可拖动元素不太熟悉,但如果我可以尝试一下,也许我们可以找出解决方案。 - Huangism
我不确定事件的触发,但如果您的目标是在第一次触摸时随手指移动箱子,则可能需要获取鼠标/触摸的x和y,并相应地移动箱子。 - Huangism
目标不是拖动 - 我原来的措辞是错误的 - 目标是在我的手指刷过它时,让touchmove事件开始在新元素上触发 - 而不必将手指抬起并再次放下。由于某些原因,我不能在父元素上侦听touchstart / touchmove事件 - 它必须在新添加的元素上。 - user1031947
哦,我明白了,我可以让它触发一次,但它无法识别您最初的触摸所产生的移动。 - Huangism
是的,我需要从初始触摸开始的移动。 - user1031947
显示剩余3条评论
3个回答

6
总结一下,您似乎想要:
  • 在touchstart事件中:显示并定位一个样式化的div元素。
  • 在touchmove事件中:拖动该元素而无需释放和重新按下鼠标按钮
如果这个解释是正确的,那么答案是在与原始点击相同的元素上处理touchmove事件,即"body"元素。不必处理您想要拖动的元素(添加的元素)的touchmove事件。
编写代码的方法肯定有很多种。以下是一种可能不完全符合您要求(主要是位置计算)但应该很容易适应的方法:
var $element = $("<div class='element' />");

$("body").on({
    'touchstart mousedown': function (e) {
        $element.appendTo("body");
        $(this).on('touchmove mousemove', move);
        move(e);//you could do `$(this).trigger('touchmove', e)` but a conventional function call keeps `move` simple.
    },
    'touchend mouseup': function (e) {
        $(this).off('touchmove mousemove');
    }
});

function move(e) {
    $element.css({
        left: (e.pageX - 10) + 'px',
        top: (e.pageY - 10) + 'px',
        cursor: 'pointer'
    });
}

mousedown/mousemove/mouseup可以用于桌面测试,但对于触摸设备使用可以删除。

演示


1
感谢您在问题规格内提供解决方案。我一直在处理与 OP 完全相同的问题。 - ChocolateAndCheese
谢谢@ChocolateAndCheese,你表达了更多的感激之情,确实比OP更有生命的迹象。 - Roamer-1888

0
如果你只需要它触发一次,那么这很容易。
function addElement() {
    $( "body" ).append( element );

    element.on( "touchmove", doStuff );
    element.trigger("touchmove"); 
}

http://jsfiddle.net/rx4qdtuj/8/

我在我的iPad模拟器上检查了这个。我用append替换了alert,这样你就不会在iPad上不断地收到警报。

如果你想让它持续触发,我唯一能想到的可能是伪造所创建元素的touchmove事件。

http://jsfiddle.net/rx4qdtuj/9/

var element = $("<div class='element' />");

$( "body" ).on( "touchstart", addElement );
$(".wrapper").on("touchmove", addElement);

function addElement() {
    $( "body" ).append( element );

    element.on( "touchmove", doStuff );
    element.trigger("touchmove"); 
}

function doStuff() {
    $('body').append('a ')
}

HTML

<div class="wrapper"></div>

CSS

.wrapper {
    position: absolute;
    top: 100px;
    left: 100px;
    width: 300px;
    height: 300px;
}

移动实际上是在已创建的 div 包装器上触发,该包装器与创建的元素位于同一位置


不幸的是,我需要touchmove自行触发,并且重复触发。 - user1031947
1
@user1031947 为什么不呢?这个元素的存在就是为了捕获 touchmove。您可以使用它来对刚创建的元素进行任何需要的操作。事实上,在 touchmove 完成后,它可以被删除。抱歉它不是父级元素,它只是另一个放置在创建的元素相同位置的元素。 - Huangism
因为在现实中,这是一个嵌入在steroidsJS层中的webView,在单独的steroids层上发生touchstart事件之后才会变得可见。这有点类似于在页面加载和初始化之前手指触摸屏幕,然后需要在页面完成初始化后检测该事件,而不需要将手指抬起并再次放下。 - user1031947
@user1031947,老实说,我不认为这是个问题。如果那个人在任何事情开始之前就把手指放在屏幕上,那么他会聪明到知道他需要在任何其他事情开始之前先做些什么。 - Huangism
1
我不在这里讨论工作流程 - 我只是想知道是否可能做到这一点。无论如何,感谢您的帮助。 - user1031947
显示剩余3条评论

-3

查看可拖动函数的文档

应用您的函数

<div id="track" class="track">
<div id="box2" style="left:0; top:0">Drag Me</div>
</div>

本地JavaScript

window.addEventListener('load', function(){

 var box2 = document.getElementById('box2'),
 boxleft, // left position of moving box
 startx, // starting x coordinate of touch point
 dist = 0, // distance traveled by touch point
 touchobj = null // Touch object holder

 box2.addEventListener('touchstart', function(e){
  touchobj = e.changedTouches[0] // reference first touch point
  boxleft = parseInt(box2.style.left) // get left position of box
  startx = parseInt(touchobj.clientX) // get x coord of touch point
  e.preventDefault() // prevent default click behavior
 }, false)

 box2.addEventListener('touchmove', function(e){
  touchobj = e.changedTouches[0] // reference first touch point for this event
  var dist = parseInt(touchobj.clientX) - startx // calculate dist traveled by touch point
 // move box according to starting pos plus dist
 // with lower limit 0 and upper limit 380 so it doesn't move outside track:
  box2.style.left = ( (boxleft + dist > 380)? 380 : (boxleft + dist < 0)? 0 : boxleft + dist ) + 'px'
  e.preventDefault()
 }, false)

}, false)

你能否在这里所写的内容上添加解释? - Huangism
由于这篇回答开头的链接非常长,请查看我回答的链接。 - alessandrio
然后粘贴或创建一个解释的简短版本,并将其放在这里。如果链接某天失效,则将没有解释。 - Huangism
在代码注释中清楚地解释。具体来说,是什么问题。 - alessandrio
3
这并没有回答我的问题。我想知道如何识别一个元素的touchmove事件,但在你手指触摸屏幕之前,它并没有添加到DOM中,因此不会触发touchstart事件。 - user1031947
循环必须从第一次触摸开始,而不是移动。 - alessandrio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接