PointerEvents: обнаружение касания «сквозного» элемента - PullRequest
0 голосов
/ 19 ноября 2018

Используя события указателя, я не могу найти подходящее событие для запуска касанием пальцами на смартфонах (протестировано с Chrome Android и Chrome Devtools с мобильной эмуляцией).

Что мне нужно: наведение курсора«событие, если вы касаетесь действия , которое проходит через элемент, удерживая палец, перемещаясь по экрану.

То есть опускайте палец за пределы элемента, перемещайтесь по нему и перемещайте палецтолько после полного прохождения элемента.

Я добавил код, отсекаемый, чтобы прояснить: мне не нужны события для синих элементов, мне нужны только соответствующие события "in / out" для красного элемента вфрагментПример JS-кода будет запускаться для мыши, но на мобильном устройстве он не вызывает никакого console.infos.

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>

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Надеюсь, я вас правильно понял. Я написал и проверил для вас два разных решения: pointerevents и touch events. В каждом событии перемещения из этих событий вы можете обнаружить текущий элемент с помощью функции document.elementFromPoint().

Раствор с пуантенвентами

Возможно, вы можете использовать pointerevents - они работают в Chrome Devtools с мобильной эмуляцией, но не работают на моем устройстве Android ( Я думаю, что мое устройство слишком старое ). Или, может быть, вы можете использовать его с Polyfill Pointer Events. Совместимость браузера для pointerevents вы можете увидеть здесь .

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>

Решение с сенсорными событиями

Но вы также можете использовать сенсорные события . К сожалению, события touchenter и touchleave были удалены из спецификации, и из-за них мы должны написать обходной путь, используя также 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>

Может быть, вам помогут следующие ссылки:

0 голосов
/ 21 ноября 2018

Попробуйте это

<script>
    var startElem = document.querySelector(".start");
    var endElem = document.querySelector(".end");
    var elem = document.querySelector(".element");

    var started = false;
    var passedThroughStart = false;
    var passedThroughEnd = false;
    var ended = false;

    startElem.addEventListener("pointerdown", function(e){
        started = true;
    });

    window.addEventListener("pointermove", function(e) {
        var x = e.clientX;
        var y = e.clientY;
        var bounds = elem.getBoundingClientRect();

        if( !passedThroughStart &&
            x > bounds.left && x < bounds.left + bounds.width &&
            y > bounds.top && y < bounds.top + bounds.height
        ){
            passedThroughStart = true;
        }

        if( passedThroughStart && !passedThroughEnd &&
            x > bounds.left && x < bounds.left + bounds.width &&
            y > bounds.top + bounds.height
        ){
            passedThroughEnd = true;
        }
    })

    window.addEventListener("pointerup", function(e) {
        var x = e.clientX;
        var y = e.clientY;
        var bounds = endElem.getBoundingClientRect();

        ended = ( x > bounds.left && x < bounds.left + bounds.width && y > bounds.top && y < bounds.top + bounds.height)

        if( started && passedThroughStart && passedThroughEnd && ended ){
            console.log("Hooray!");
        }

        started = false;
        passedThroughStart = false;
        passedThroughEnd = false;
        ended = false;
    });
</script>

В качестве альтернативы используйте pointerenter и pointerleave вместо pointermove

elem.addEventListener('pointenter', function(e) {
    passedThroughStart = true;
}
elem.addEventListener('pointleave', function(e) {
    passedThroughEnd = true;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...