Как лучше всего моделировать наведение мыши в мобильных браузерах с помощью сенсорных событий? - PullRequest
1 голос
/ 29 февраля 2020

У меня есть простой пользовательский интерфейс, который позволяет пользователям в настольных браузерах нажимать на ячейку в сетке, и, удерживая кнопку мыши нажатой, перемещать мышь вокруг, чтобы очень быстро выделить несколько ячеек. Я выполняю sh это с mousedown, mouseover и mouseup событиями на document и использую логический флаг, чтобы определить, удерживается ли кнопка мыши в нажатом положении. Он отлично работает в настольных браузерах.

Проблема в мобильных браузерах. Эти события мыши не существуют, и я знаю, что вместо этого нам нужно использовать события touch, но после тщательного поиска в Google, SO и т. Д. 1016 *. Я не могу найти последовательный, работоспособный способ сделать то же самое в мобильных браузерах.

Самое близкое, что я видел, это захват начала с touchstart, а затем отслеживание движения пальца с помощью touchmove и evt.touches[0].clientX/Y свойств. Есть ли лучший / более простой способ сделать это, или мы вынуждены в основном проверять координаты экрана с помощью clientX/Y, чтобы выяснить, над каким элементом DOM мы «наводим курсор» и, соответственно, выделить элемент DOM?

Ответы [ 2 ]

0 голосов
/ 29 февраля 2020

Спасибо всем за помощь в решении этой проблемы. Метод document.elementFromPoint был действительно ключом, который сделал все это возможным без тонны лишнего кода.

Вот пример используемого кода, позволяющий выделение ячеек сетки, которое я искал как на настольном, так и на мобильном устройстве, когда Используемый щелкает мышью / стучит пальцем по экрану и начинает двигать мышью / пальцем:

var isTouchDevice = 'ontouchstart' in document.documentElement;
var isActivelySelecting = false;
var currHoverTarget = null;

if (isTouchDevice) { // Mobile version
    document.addEventListener('touchstart', (evt) => {
        var target = evt.target;

        if (target.classList.contains('class-name-of-selectable-grid-cells')) {
            isActivelySelecting = true;
            currHoverTarget = target;
            toggleSelection(target); // Function for storing selected cells in an array

            // For turning off text highlighting as you select cells
            document.querySelector('body').classList.add('noHighlighting');

            // Stops screen from scrolling on mobile while selecting cells.
            evt.preventDefault();
        }
    }, {
        passive: false // Needed to avoid errors in some browsers.
    });

    document.addEventListener('touchmove', (evt) => {
        if (isActivelySelecting) {
            var target = evt.target;

            if (target.classList.contains('class-name-of-selectable-grid-cells')) {
                var x = evt.touches[0].clientX;
                var y = evt.touches[0].clientY;
                var hoveredElem = document.elementFromPoint(x, y); // The secret sauce

                // Only true when going from one DOM element to another.
                // Basically simulates the mouseover event for desktop browsers.
                if (hoveredElem !== currHoverTarget) {
                    currHoverTarget = hoveredElem;
                    toggleSelection(hoveredElem); // Function for storing selected cells in an array
                }
            }
        }
    });

    document.addEventListener('touchend', () => {
        isActivelySelecting = false;
        currHoverTarget = false;

        document.querySelector('body').classList.remove('noHighlighting');
    });
} else { // Desktop version
    document.addEventListener('mousedown', (evt) => {
        var target = evt.target;

        if (target.classList.contains('class-name-of-selectable-grid-cells')) {
            isActivelySelecting = true;
            toggleSelection(target); // Function for storing selected cells in an array

            // For turning off text highlighting as you select cells
            document.querySelector('body').classList.add('noHighlighting');
        }
    });

    document.addEventListener('mouseover', (evt) => {
        if (isActivelySelecting) {
            var target = evt.target;

            if (target.classList.contains('class-name-of-selectable-grid-cells')) {
                toggleSelection(target); // Function for storing selected cells in an array
            }
        }
    });

    document.addEventListener('mouseup', () => {
        isActivelySelecting = false;

        document.querySelector('body').classList.remove('noHighlighting');
    });
}
0 голосов
/ 29 февраля 2020

Я думаю, что вы на правильном пути. Я должен был сделать нечто подобное на этой неделе. Один совет:

Когда срабатывает событие onTouchStart, установите событие onTouchMove на document таким образом, чтобы оно срабатывало, даже если пользователь выходит за элемент, вызвавший начальное событие. (Это может не относиться к вашему указанному c интерфейсу пользователя)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...