防止在elementFromPoint上触发mousemove

时间:2015-02-19 04:55:42

标签: javascript google-chrome

DEMO:http://jsfiddle.net/2FWZD/

这是jsfiddle代码,因为它迫使我添加代码:

$(document).ready(function () {
    $('.test').on('mousemove', function (e) {
        counter++;
        $('.counter').text(counter);

        $(this).hide();
        // Comment out the following line and counter will stop increasing
        document.elementFromPoint(e.clientX, e.clientY);
        $(this).show();
    });
});

这种情况发生在chrome中,无论如何都要阻止这个或另一种方法来解决elementFromPoint?

此处详细说明了Bug:https://code.google.com/p/chromium/issues/detail?id=333623


编辑1:

我只想注意,虽然答案是对jsfiddle演示的破解者,它实际上并没有解决我的潜在问题。

我正在使用Leap Motion在网站上模拟鼠标,该网站发送模拟的mousedown和mouseup事件以及mousemoves。我使用画布将光标绘制在所有内容的顶部,并使用此处显示的技术访问画布下方的元素。这样做的鼠标移动是在REAL鼠标位置触发而不是我的模拟鼠标,有效地给了我奇怪的问题。

这对FireFox来说不是问题。


编辑2:

问题解决。见答案。使用hide()之外的其他隐藏方法似乎可以在不触发的情况下工作

4 个答案:

答案 0 :(得分:5)

保持最后的位置,就像这样:

var counter = 0;
var last='';
$(document).ready(function () {
    $('.test').on('mousemove', function (e) {
        var cur=e.screenX+':'+e.screenY;
        if (cur == last) return;
        last = cur;
        counter++;
        $('.counter').text(counter);

        $(this).hide();
        // Comment out the following line and counter will stop increasing
        document.elementFromPoint(e.clientX, e.clientY);
        $(this).show();
    });
});

其他方式似乎是通过使用css:

使其“隐形”来隐藏元素
var counter = 0;

$(document).ready(function () {
    $('.test').on('mousemove', function (e) {
        counter++;
        $('.counter').text(counter);

        $(this).addClass('hidden');
        // Comment out the following line and counter will stop increasing
        console.log(document.elementFromPoint(e.clientX, e.clientY));
        $(this).removeClass('hidden');
    });
});

的CSS:

.test.hidden {
    overflow: hidden;
    width: 0;
    height: 0;
    margin: 0;
    padding: 0;
}

http://jsfiddle.net/2FWZD/10/

答案 1 :(得分:2)

elementFromPoint()将返回特定坐标的元素。在这种情况下,指针/光标下的元素。在示例代码中,elementFromPoint()函数返回<html>,因为隐藏了.test。出于某种原因,这导致Chrome认为鼠标正在移动。但是,您可以使用querySelectorAll(":hover")代替elementFromPoint()

jsfiddle demo

var counter = 0;

$(document).ready(function () {
    $('.test').not( "body" ).on('mousemove', function (e) {
        counter++;
        $('.counter').text(counter);

        $(this).hide();

        // Comment out the following line and counter will stop increasing
        var el=document.querySelectorAll( ":hover" ); //el = html not .test because it is hidden
        console.log(el);
        $(this).show();
    });
});

答案 2 :(得分:1)

以下是问题发生的可能原因:

浏览器优化尽可能少的重绘,以提供更流畅的观看体验。这意味着在可能的情况下,像这样的块

$(this).hide();
$(this).show();

在可能的情况下优化为无操作。然而,当在两个操作之间强制重绘时不是这种情况,例如,您的代码

$(this).hide();
document.elementFromPoint(e.clientX, e.clientY);
$(this).show();

或者,有时用作黑客以避免在不需要时进行优化

$(this).hide();
this.offsetHeight;
$(this).show();

在某些情况下,似乎再次显示该元素会在Chrome上触发mousemove

答案 3 :(得分:1)

简而言之

不要使用$(元素).hide()。 Chrome存在问题(并成为我们的新IE6)。

而不是那只是简单的讲义,你试图做一个getElementFromPoint

,你不想显示.test - 元素

See solution in jsFiddle

长版本

此时Chrome无法处理&#39; display:none&#39;在CSS中,将重绘总元素。这将引发mousemove事件,因此它将成为一个永恒的循环。

除了使用display:none之外,您还可以将&#39; height&#39; 设为零,这对于选择正确的元素具有相同的效果。 出于这个原因,我创建了一个函数fastDraw

.hide()变为fastDraw
function fastDraw($box, show){
    if(show){
        $box.css({'height': $box.data('height')});
    } else {
        $box.data('height', $box.height());
        $box.css({'height': 0});
    }
}

现在你得到相同的结果

fastDraw($box); //hides the element by setting the height zero
var element = document.elementFromPoint(e.clientX, e.clientY); //fetches the element
fastDraw($box, true); //return it back to the previous height

优化

由于您正在使用mouseMove事件,因此它将被调用很多次,并且最好尽可能少地执行。我已经重构了一些东西,所以它的计算量会减少。