javascript - 指针事件 : Detect touching "through" an element

标签 javascript android dom smartphone pointer-events

使用指针事件,我找不到正确的事件来触发智能手机上基于手指的触摸(使用 Chrome Android 和 Chrome Devtools 进行了移动仿真测试)。

我需要的是:如果您触摸 Action 穿过 一个元素,同时按住手指在屏幕上移动,则发生“悬停”事件。

即手指在元素外向下,移动穿过元素,完全穿过元素后才向上移动手指。

我附上了一个代码 fragment 以明确:我不需要蓝色元素的事件,我只需要 fragment 中红色元素的相应“输入/输出”事件。示例 JS 代码将为鼠标触发,但在移动设备上它不会触发任何控制台信息。

var elem = document.querySelector(".element");

elem.addEventListener("pointerover", function() {
    console.clear();
    console.info("pointerover triggered");
});
elem.addEventListener("pointerenter", function() {
    console.clear();
    console.info("pointerenter triggered");
});
elem.addEventListener("pointerleave", function() {
    console.clear();
    console.info("pointerleave triggered");
});
.outer {
    width: 100px;
    height: 100px;
    border: 3px solid grey;
    font-size: 12px;
    color: white;
    text-align:center;
    touch-action: none;
    
}

.start {
   position: relative;
   top:0px;
   left:0px;
   width: 100px;
   height: 20px;
   background-color: blue;
}

.element {
   position: relative;
   top: 20px;
   left: 0px;
   width: 100px;
   height: 20px;
   background-color: red;
}

.end {
   position: relative;
   top: 40px;
   right: 0;
   width: 100px;
   height: 20px;
   background-color: blue;
}
<div class="outer">
    <div class="start">Start touch here</div>
    <div class="element">Move over here</div>
    <div class="end">End touch here</div>
</div>

最佳答案

希望我对您的理解是正确的。我为您编写并测试了两种不同的解决方案:指针事件和触摸事件。在此事件的每个移动事件中,您可以使用函数 document.elementFromPoint() 检测当前元素。 .

指针事件解决方案

也许您可以使用 pointerevents – 它们可以在 Chrome Devtools 中使用移动仿真运行,但不能在我的 Android 设备上运行(我认为我的设备太旧了)。或者你可以将它与 Pointer Events Polyfill 一起使用。您可以查看指针事件的浏览器兼容性 here .

var elementFromPoint,
    isFingerDown = false,
    isThroughElemMoved = false,
    elem = document.querySelector('.element'),
    output = document.querySelector('#output');

document.addEventListener('pointerdown', function(e)
{
    if(elem != e.target)
    {
        isFingerDown = true;
        output.innerHTML = 'pointer-START';
    }
});

document.addEventListener('pointermove', function(e)
{
    elementFromPoint = document.elementFromPoint(e.pageX - window.pageXOffset, e.pageY - window.pageYOffset);

    if(elem == elementFromPoint)
    {
        isThroughElemMoved = true;
        output.innerHTML = 'pointer-MOVE';
    }
});

document.addEventListener('pointerup', function(e)
{
    if(isFingerDown && isThroughElemMoved && elem != elementFromPoint)
        output.innerHTML = 'It is done!';

    isFingerDown = isThroughElemMoved = false;
});
.outer
{
    width: 100px;
    height: 100px;
    border: 3px solid grey;
    font-size: 12px;
    color: white;
    text-align: center;
    /*touch-action: none*/
}
.outer div{position: relative; left: 0; height: 20px}
.start{top: 0; background: blue}
.element{top: 20px; background: red}
.end{top: 40px; background: blue}
<div class="outer">
    <div class="start">Start touch here</div>
    <div class="element">Move over here</div>
    <div class="end">End touch here</div>
</div>
<br><br>
<div id="output">info</div>

触摸事件解决方案

但是你可以使用 touch events 也是。不幸的是,事件 touchentertouchleave 已从规范中删除,因此我们也必须使用 document.elementFromPoint() 编写解决方法.

以下代码段仅适用于移动仿真(使用 Chrome Devtools 测试)或支持触摸事件的设备(使用 Android 测试)。

var elementFromPoint,
    isFingerDown = false,
    isThroughElemMoved = false,
    elem = document.querySelector('.element'),
    output = document.querySelector('#output');

document.addEventListener('touchstart', function(e)
{
    if(elem != e.target)
    {
        isFingerDown = true;
        output.innerHTML = 'touch-START';
    }
});

document.addEventListener('touchmove', function(e)
{
    var touch = e.touches[0];
    
    elementFromPoint = document.elementFromPoint(touch.pageX - window.pageXOffset, touch.pageY - window.pageYOffset);

    if(elem == elementFromPoint)
    {
        isThroughElemMoved = true;
        output.innerHTML = 'touch-MOVE';
    }
});

document.addEventListener('touchend', function(e)
{
    if(isFingerDown && isThroughElemMoved && elem != elementFromPoint)
        output.innerHTML = 'It is done!';

    isFingerDown = isThroughElemMoved = false;
});
.outer
{
    width: 100px;
    height: 100px;
    border: 3px solid grey;
    font-size: 12px;
    color: white;
    text-align: center;
    /*touch-action: none*/
}
.outer div{position: relative; left: 0; height: 20px}
.start{top: 0; background: blue}
.element{top: 20px; background: red}
.end{top: 40px; background: blue}
<div class="outer">
    <div class="start">Start touch here</div>
    <div class="element">Move over here</div>
    <div class="end">End touch here</div>
</div>
<br><br>
<div id="output">info</div>

也许以下链接可以帮助您:

关于javascript - 指针事件 : Detect touching "through" an element,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53376909/

相关文章:

JavaScript/不区分大小写

android - 无法使用适用于 Android 的 Google Cloud Messaging(不是帮助程序库)接收消息

java - 如何从 android 查询 Firebase 中是否存在值数组?

php - 有没有更好的方法来更改 PHP 中的 DOMElement->tagName 属性?

javascript - 将数组转换为对象以选择对象(重构/优化)

javascript - 如何在 Typescript 和 Angular 2 中使用 "@input set"检索数据?

javascript - 如何在 express js 中访问使用 app.set() 设置的变量

android - 深度链接和多个应用实例

javascript - 设置输入内容失败

javascript - 如何获取 <td> 内的跨度值(表数据),当单击也在 <td> 内的按钮时