javascript 在 touchmove 期间切换到新元素

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12396635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 16:05:30  来源:igfitidea点击:

Crossing over to new elements during touchmove

javascriptjquerytouch

提问by spike

I'd like to make it so that as you drag your finger over a set of elements, the background of the one you've got your finger on changes.

我想让它当你将手指拖过一组元素时,你手指上的那个背景会发生变化。

It seems like I want to use the touchmove event for this, but as far as I can tell the target element never changes, even as you drag around. The clientX and clientY do change, and I found this document.elementFromPointfunction that works in chrome, but seems very roundabout (plus I'm not sure which browsers support it)

似乎我想为此使用 touchmove 事件,但据我所知,即使您四处拖动,目标元素也不会改变。clientX 和 clientY 确实发生了变化,我发现这个document.elementFromPoint功能在 chrome 中有效,但看起来很迂回(另外我不确定哪些浏览器支持它)

See this fiddle, I want the boxes to turn green as you touch through them:

看到这个小提琴,我希望盒子在你触摸它们时变成绿色:

http://jsfiddle.net/QcQYa/9/

http://jsfiddle.net/QcQYa/9/

By the way, in chrome, you'll need to go into the user agent tab of the inspector config modal and choose "emulate touch events" to see my example.

顺便说一下,在 chrome 中,您需要进入检查器配置模式的用户代理选项卡并选择“模拟触摸事件”以查看我的示例。

Edit:I found an idea to use mouseenterhere How to detect html elements on touchmoveand got it to work on desktop chrome, but not on mobile safari.

编辑:我在mouseenter这里找到了一个想法如何在 touchmove 上检测 html 元素并让它在桌面 chrome 上工作,但不能在移动 safari 上使用。

采纳答案by dan-lee

I took a different approach:

我采取了不同的方法:

Every touch event I check if the touch position is inside a $('.catch')object.

每个触摸事件我都会检查触摸位置是否在$('.catch')对象内部。

function highlightHoveredObject(x, y) {
    $('.catch').each(function() {
      // check if is inside boundaries
      if (!(
          x <= $(this).offset().left || x >= $(this).offset().left + $(this).outerWidth() ||
          y <= $(this).offset().top  || y >= $(this).offset().top + $(this).outerHeight()
      )) {

        $('.catch').removeClass('green');
        $(this).addClass('green');
      }
    });
}

You can see it working on jsFiddle.
It works on Chrome, I hope it also does on mobile devices.

你可以看到它在jsFiddle 上工作。
它适用于 Chrome,我希望它也适用于移动设备。

Edit:
In this fiddleI used both versions, mine and that one from the link in the comments (document.elementFromPoint – a jQuery solution), both seem to work on my Android phone. I also added a quick and dirty benchmark (see console) and as expected document.elementFromPointis a few thousandth faster, if that is your concern you should check the support of document.elementFromPointfor the browsers you want to support.

编辑
这个小提琴中,我使用了两个版本,我的和评论中链接的那个版本(document.elementFromPoint – jQuery 解决方案),两者似乎都适用于我的 Android 手机。我还添加了一个快速而肮脏的基准测试(参见控制台),正如预期的那样,document.elementFromPoint速度提高了千分之一,如果这是您的问题,您应该检查document.elementFromPoint您想要支持的浏览器的支持。

回答by Nelson

You'll find my solution in this fiddle, I tested it on my android phone and it works fine, it uses jquerymobile to take advantage of vmousemoveevent, it also attachs a handler to touchmoveevent just to prevent scrolling the browser view on the mobile device.

你会在这个小提琴中找到我的解决方案,我在我的 android 手机上测试了它并且它工作正常,它使用 jquerymobile 来利用vmousemove事件,它还附加一个处理程序到touchmove事件只是为了防止在移动设备上滚动浏览器视图。

I paste here the relevant HTML and javascript bits:

我在这里粘贴相关的 HTML 和 javascript 位:

<div id="main" ontouchmove="touchMove(event);">
   <span class='catch'>One</span>
   <span class='catch'>Two</span>
   <span class='catch'>Three</span>
   <span class='catch'>Four</span>
   <span class='catch'>Five</span>
   <span class='catch'>Six</span>
   <span class='catch'>Seven</span>
</div>

now the javascript:

现在是 javascript:

function elem_overlap(jqo, left, top) {
   var d = jqo.offset();
   return top >= d.top && left >= d.left && left <= (d.left+jqo[0].offsetWidth)
          && top <= (d.top+jqo[0].offsetHeight);
}

/* To prevent WebView from scrolling on swipe, see http://goo.gl/DIZbm */
touchMove = function(event) {
   event.preventDefault(); //Prevent scrolling on this element
}

$("#main").bind("vmousemove", function(evt){
   $('.catch').each(function(index) {
      if ( elem_overlap($(this), evt.pageX, evt.pageY) ) {
         $('.catch').not('eq('+index+')').removeClass('green');
         if (!$(this).hasClass('green')) {
            $(this).addClass('green');
         }
      }
   });
});

回答by Jaibuu

You can't "trigger a touchend event" or cancel touches, which you would need to start touching another.

您不能“触发 touchend 事件”或取消触摸,而您需要开始触摸另一个。

So you would be better off binding the touchmove event to the container, and manipulating the boxes based on their position/sizes and the touch position, like what part of Dan Lee's answer does.

因此,您最好将 touchmove 事件绑定到容器,并根据它们的位置/大小和触摸位置来操作框,就像 Dan Lee 的答案的一部分那样。