防止鼠标移动对elementFromPoint的攻击
Prevent mousemove fire upon elementFromPoint
演示: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事件以及鼠标移动。我使用画布在所有内容的顶部绘制光标,并使用此处显示的技术访问画布下方的元素。这样做后,鼠标移动是在真实的鼠标位置触发的,而不是我的模拟鼠标,这实际上给了我一些奇怪的问题。
这不是FireFox的问题。
编辑2:
问题解决了。请参阅答案。使用hide()之外的其他隐藏方法似乎可以在不触发的情况下工作
只保留最后一个位置,如下所示:
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/
elementFromPoint()
将返回特定坐标的元素。在这种情况下,指针/光标下的元素。在示例代码中,elementFromPoint()
函数返回<html>
,因为.test
是隐藏的。出于某种原因,这导致Chrome认为鼠标在移动。但是,您可以使用querySelectorAll(":hover")
而不是elementFromPoint()
。
jsfiddle演示
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();
});
});
以下是问题发生的可能原因:
浏览器进行优化,尽可能少地重新绘制,以提供更流畅的查看体验。这意味着,在可能的情况下,像这样的块
$(this).hide();
$(this).show();
在可能的情况下被优化为无操作。然而,当在两个操作之间强制重绘时,情况并非如此,例如,您的代码就是这样
$(this).hide();
document.elementFromPoint(e.clientX, e.clientY);
$(this).show();
或者,有时被用作黑客攻击,以避免在不需要时进行优化
$(this).hide();
this.offsetHeight;
$(this).show();
在某些情况下,再次显示元素似乎会触发Chrome上的mousemove
。
简而言之
不要使用$(element).hide()。Chrome有问题(成为我们的新IE6)。
当尝试执行getElementFromPoint 时,您不想显示.test-元素,而不是仅仅分发css自己
请参阅jsFiddle 中的解决方案
长版本
Chrome目前无法处理CSS中的"display:none",将重新绘制总元素。这将引发mousemove事件,从而使其成为一个永恒的循环。
不使用display:none,您也可以只将"height"设置为零,这将对选择正确的元素具有相同的效果。基于此,我制作了一个函数fastDraw
.hide()变为fastDrawfunction 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事件,它将被调用很多次,最好尽可能少地调用。我已经重构了一些东西,所以它会做更少的计算。
- 没有找到相关文章