How do I efficiently highlight element under mouse cursor with an overlay?

匿名 (未验证) 提交于 2019-12-03 01:50:02

问题:

Still trying to answer this question, and I think I finally found a solution, but it runs too slow.

var $div = $('
') .css({ 'border': '1px solid red', 'position': 'absolute', 'z-index': '65535' }) .appendTo('body'); $('body *').live('mousemove', function(e) { var topElement = null; $('body *').each(function() { if(this == $div[0]) return true; var $elem = $(this); var pos = $elem.offset(); var width = $elem.width(); var height = $elem.height(); if(e.pageX > pos.left && e.pageY > pos.top && e.pageX topElement.zIndex) { topElement = { 'node': $elem, 'zIndex': zIndex }; } } }); if(topElement != null ) { var $elem = topElement.node; $div.offset($elem.offset()).width($elem.width()).height($elem.height()); } });

It basically loops through all the elements on the page and finds the top-most element beneath the cursor.

Is there maybe some way I could use a quad-tree or something and segment the page so the loop runs faster?

回答1:

Is there maybe some way I could use a quad-tree or something and segment the page so the loop runs faster?

Just step back a bit, realize how small the problem is, and that the harder your try the more complicated answer you will use.

Now what you need to do is to create 4 elements for the highlighting. They will form an empty square, and so your mouse events are free to fire. This is similar to this overlay example I've made.

The difference is that you only need the four elements (no resize markers), and that the size and position of the 4 boxes are a bit different (to mimick the red border). Then you can use event.target in your event handler, because it gets the real topmost element by default.

Another approach is to hide the exra element, get elementFromPoint, calculate then put it back.

They're faster than light, I can tell you. Even Einstein would agree :)

1.) elementFromPoint overlay/borders - [Demo1] FF needs v3.0+

var box = $("
").css({ display: "none", position: "absolute", zIndex: 65000, background:"rgba(255, 0, 0, .3)" }).appendTo("body"); var mouseX, mouseY, target, lastTarget; // in case you need to support older browsers use a requestAnimationFrame polyfill // e.g: https://gist.github.com/paulirish/1579671 window.requestAnimationFrame(function frame() { window.requestAnimationFrame(frame); if (target && target.className === "outer") { box.hide(); target = document.elementFromPoint(mouseX, mouseY); } box.show(); if (target === lastTarget) return; lastTarget = target; var $target = $(target); var offset = $target.offset(); box.css({ width: $target.outerWidth() - 1, height: $target.outerHeight() - 1, left: offset.left, top: offset.top }); }); $("body").mousemove(function (e) { mouseX = e.clientX; mouseY = e.clientY; target = e.target; });

2.) mouseover borders - [Demo2]



回答2:

First off, i don't think doing $('body *').live is a very good idea, it seems very expensive (think about the kind of calculation the browser has to do every time you move your mouse)

That said, here is an optimized version that ignores that aspect

var $div = $('
') .css({ 'border': '1px solid red', 'position': 'absolute', 'z-index': '65535' }) .appendTo('body'); $('body *').live('mousemove', function(e) { var topElement = null; var $bodyStar = $('body *'); for(var i=0,elem;elem=$bodyStar[i];i++) { if(elem == $div[0]) continue; var $elem = $(elem); var pos = $elem.offset(); var width = $elem.width(); var height = $elem.height(); if(e.pageX > pos.left && e.pageY > pos.top && e.pageX topElement.zIndex) { topElement = { 'node': $elem, 'zIndex': zIndex }; } } } if(topElement != null) { var $elem = topElement.node; $div.offset($elem.offset()).width($elem.width()).height($elem.height()); } });

For future reference, never use jQuerys looping mechanisms if you need performance. They are all build around function calls for every iteration, which is very slow compared to a normal loop, since the call stack initiation that happens when you do a function call is a huge overhead for most iteration operations you need to do.

Code updated to fix errors, and allow for dynamically inserted elements.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!