简体   繁体   English

Javascript 在 touchstart 的 DOM 中移动 event.target 后 touchmove 事件不工作

[英]Javascript touchmove event not working after event.target moved in DOM in touchstart

I have several svg use elements within an svg element, with event handlers for touchstart/move/end attached to the svg element.我在svg元素中有几个svg use元素, touchstart/move/end的事件处理程序附加到svg元素。 When a user touches the svg use element on the screen and moves their finger around, the element moves around the screen as desired.当用户触摸屏幕上的svg use元素并四处移动手指时,该元素会根据需要在屏幕上移动。

//Exact code in fiddle is different, this is example
<svg id="parent" viewBox="0 0 1000 1000">
   <use href="test.svg" width="100" height="100" x="100" y="100">
   <use href="test2.svg" width="100" height="100" x="100" y="100">
</svg>
//Exact code in fiddle is different, this is example
let parentSVG = document.getElementById("parent");
parentSVG.addEventListener('touchstart', Handle_DragStart); //mousedown too
parentSVG.addEventListener('touchmove', Handle_Drag); //mousemove too
parentSVG.addEventListener('touchend', Handle_DragEnd); //mouseup too

The problem is that I want the dragged element to always be drawn on top of the others, and the elements are drawn in DOM-order (first element in DOM first).问题是我希望拖动的元素始终绘制在其他元素之上,并且元素按 DOM 顺序绘制(首先是 DOM 中的第一个元素)。 To handle this, in my touchstart event handler I'm moving the element the user touched to the end of the list via appendChild() :为了处理这个问题,在我的touchstart事件处理程序中,我通过appendChild()将用户触摸的元素移动到列表的末尾:

//Exact code in fiddle is different, this is example
let mid_move = false;
function Handle_DragStart (event)
{
   //Needed to ignore other touch events while dragging
   if(mid_move)
      return;
   mid_move = true;

   //The event.target is the svg use element. 
   //It is already attached to the parentSVG. 
   //This just moves it to the end of the list of children. 
   parentSVG.appendChild(event.target);
}

This works like a charm for mousedown and mousemove but not touchstart and touchmove .这就像mousedownmousemove的魅力,但不是touchstarttouchmove After doing this the touchmove event doesn't fire until I touch the screen a second time, presumably because the appendChild() call in the touchstart handler doesn't change anything at that point?这样做之后, touchmove事件不会触发,直到我第二次触摸屏幕,大概是因为touchstart处理程序中的appendChild()调用此时没有改变任何东西?

Am I invalidating the event?我要使事件无效吗? How should I handle this situation?我应该如何处理这种情况?

EDIT:编辑:

JSFiddle example. JSFiddle 示例。 //Set append_child to true/false to see behavior // 将 append_child 设置为 true/false 以查看行为

I circumvented the problem with a modified form of @JanStránský suggestion.我用@JanStránský 建议的修改形式规避了这个问题。 I placed a transparent svg rectangle covering the entire drag area to act as a drag surface, and listed this at the end of the list of svg elements.我放置了一个覆盖整个拖动区域的透明 svg 矩形作为拖动表面,并将其列在 svg 元素列表的末尾。

Then when handling touchstart , I used the mouse position to determine which svg element underneath this clear svg rectangle the user was selecting.然后在处理touchstart时,我使用鼠标 position 来确定用户选择了这个清晰的 svg 矩形下方的哪个 svg 元素。 I then called parentSVG.insertBefore(selected, clear_rect) so that the element was drawn above everything else but beneath this drag surface (so subsequent drags would work).然后我调用parentSVG.insertBefore(selected, clear_rect)以便该元素被绘制在所有其他元素之上但在此拖动表面之下(因此后续拖动将起作用)。

The draggable elements are all laid out in (and snapped-to) a grid, so mouse position -> selected element is easily determined.可拖动元素全部布置在(并对齐)网格中,因此鼠标 position -> 选定元素很容易确定。 Otherwise you may need one clear rect per draggable element as suggested.否则,您可能需要按照建议为每个可拖动元素使用一个清晰的矩形。

This solution seems to prevent me from using CSS features cursor: grab;这个解决方案似乎阻止我使用 CSS 功能cursor: grab; when over the element since the large drag surface is in the way.当在元素上方时,因为大的阻力表面挡住了路。 Maybe I'll just implement it manually.也许我会手动实现它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM