Javascript 在带有触摸事件的移动浏览器上模拟鼠标悬停的最佳方式是什么?

Javascript 在带有触摸事件的移动浏览器上模拟鼠标悬停的最佳方式是什么?,javascript,touch-event,mobile-browser,touchstart,Javascript,Touch Event,Mobile Browser,Touchstart,我有一个简单的UI,允许桌面浏览器上的用户点击网格中的一个单元格,在按住鼠标按钮的同时,移动鼠标以快速高亮显示多个单元格。我通过文档上的mousedown、mouseover和mouseup事件来实现这一点,并使用布尔标志指示鼠标按钮是否被按下。它在桌面浏览器上运行良好 但问题在于移动浏览器。这些鼠标事件并不存在,我知道我们需要使用touch事件来代替,但是在谷歌搜索了这么多之后,我找不到一个一致的、可行的方法在移动浏览器上做同样的事情 我见过的最近的一个例子是用touchstart捕捉开始,然

我有一个简单的UI,允许桌面浏览器上的用户点击网格中的一个单元格,在按住鼠标按钮的同时,移动鼠标以快速高亮显示多个单元格。我通过
文档
上的
mousedown
mouseover
mouseup
事件来实现这一点,并使用布尔标志指示鼠标按钮是否被按下。它在桌面浏览器上运行良好

但问题在于移动浏览器。这些鼠标事件并不存在,我知道我们需要使用
touch
事件来代替,但是在谷歌搜索了这么多之后,我找不到一个一致的、可行的方法在移动浏览器上做同样的事情


我见过的最近的一个例子是用
touchstart
捕捉开始,然后用
touchmove
evt.touchs[0].clientX/Y
属性跟踪手指的运动。是否有更好/更简单的方法来实现这一点,或者我们被迫基本上使用
clientX/Y
检查屏幕坐标,以确定我们“悬停在”哪个DOM元素上并相应地高亮显示该DOM元素

我认为你找到了正确的解决方案。本周我不得不做类似的事情。有一条建议是:


当触发
onTouchStart
事件时,在
文档上设置
onTouchMove
事件,这样即使用户移动到触发初始事件的元素之外,它也会触发。(这可能与您的特定UI无关)

我认为您找到了正确的解决方案。本周我不得不做类似的事情。有一条建议是:


当触发
onTouchStart
事件时,在
文档上设置
onTouchMove
事件,这样即使用户移动到触发初始事件的元素之外,它也会触发。(这可能与您的特定UI无关)

感谢大家在解决此问题时的帮助。
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');
    });
}

感谢大家在解决这个问题上的帮助。
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');
    });
}

谢谢你,杰拉德。是的,我在
document
对象上设置了
touchmove
,所以我开始了。因此,基本上,对于每个
touchmove
,我必须计算我是新悬浮在DOM元素上还是悬浮在现有DOM元素之外,并相应地做我想做的一切?基本上,我们必须为触摸事件手动重新编码
mouseover
mouseout
,是吗?啊!真痛苦,谢谢你,杰拉德。是的,我在
document
对象上设置了
touchmove
,所以我开始了。因此,基本上,对于每个
touchmove
,我必须计算我是新悬浮在DOM元素上还是悬浮在现有DOM元素之外,并相应地做我想做的一切?基本上,我们必须为触摸事件手动重新编码
mouseover
mouseout
,是吗?啊!多痛苦啊。您使用
touchstart
touchmove
touchend
无疑是正确的,显然有
document.elementFromPoint(event.clientX,event.clientY)
,每个
文档。elementFromPoint
方法非常方便。这将节省大量时间(希望如此)。谢谢。您使用
touchstart
touchmove
touchend
无疑是正确的,显然有
document.elementFromPoint(event.clientX,event.clientY)
,每个
文档。elementFromPoint
方法非常方便。这将节省大量时间(希望如此)。谢谢