jQuery:在鼠标光标下突出显示元素?

时间:2011-01-15 05:57:49

标签: jquery

  

可能重复:
  How to make this JavaScript much faster?

我正在尝试在jQuery中创建一个“元素选择器”,就像Firebug一样。基本上,我想突出显示用户鼠标下方的元素。这是我到目前为止所得到的,但效果并不好:

$('*').mouseover(function (event) {
    var $this = $(this);
    $div.offset($this.offset()).width($this.width()).height($this.height());
    return false;
});


var $div = $('<div>')
    .css({ 'background-color': 'rgba(255,0,0,.5)', 'position': 'absolute', 'z-index': '65535' })
    .appendTo('body');

基本上,我将一个div注入到具有半透明背景的DOM中。然后我在每个元素上侦听鼠标悬停事件,然后移动div以覆盖该元素。

现在,只要您将鼠标移到页面上,这只会使整个页面变为红色。我怎样才能让它更好地工作?

编辑:非常确定问题是,只要我的鼠标触摸页面,身体就会被选中,然后当我移动鼠标时,没有任何一个瞬间通过高点因为它超越了一切。


萤火虫

通过Firebug源代码挖掘,我发现了这个:

drawBoxModel: function(el)
{
    // avoid error when the element is not attached a document
    if (!el || !el.parentNode)
        return;

    var box = Firebug.browser.getElementBox(el);

    var windowSize = Firebug.browser.getWindowSize();
    var scrollPosition = Firebug.browser.getWindowScrollPosition();

    // element may be occluded by the chrome, when in frame mode
    var offsetHeight = Firebug.chrome.type == "frame" ? FirebugChrome.height : 0;

    // if element box is not inside the viewport, don't draw the box model
    if (box.top > scrollPosition.top + windowSize.height - offsetHeight ||
        box.left > scrollPosition.left + windowSize.width ||
        scrollPosition.top > box.top + box.height ||
        scrollPosition.left > box.left + box.width )
        return;

    var top = box.top;
    var left = box.left;
    var height = box.height;
    var width = box.width;

    var margin = Firebug.browser.getMeasurementBox(el, "margin");
    var padding = Firebug.browser.getMeasurementBox(el, "padding");
    var border = Firebug.browser.getMeasurementBox(el, "border");

    boxModelStyle.top = top - margin.top + "px";
    boxModelStyle.left = left - margin.left + "px";
    boxModelStyle.height = height + margin.top + margin.bottom + "px";
    boxModelStyle.width = width + margin.left + margin.right + "px";

    boxBorderStyle.top = margin.top + "px";
    boxBorderStyle.left = margin.left + "px";
    boxBorderStyle.height = height + "px";
    boxBorderStyle.width = width + "px";

    boxPaddingStyle.top = margin.top + border.top + "px";
    boxPaddingStyle.left = margin.left + border.left + "px";
    boxPaddingStyle.height = height - border.top - border.bottom + "px";
    boxPaddingStyle.width = width - border.left - border.right + "px";

    boxContentStyle.top = margin.top + border.top + padding.top + "px";
    boxContentStyle.left = margin.left + border.left + padding.left + "px";
    boxContentStyle.height = height - border.top - padding.top - padding.bottom - border.bottom + "px";
    boxContentStyle.width = width - border.left - padding.left - padding.right - border.right + "px";

    if (!boxModelVisible) this.showBoxModel();
},

hideBoxModel: function()
{
    if (!boxModelVisible) return;

    offlineFragment.appendChild(boxModel);
    boxModelVisible = false;
},

showBoxModel: function()
{
    if (boxModelVisible) return;

    if (outlineVisible) this.hideOutline();

    Firebug.browser.document.getElementsByTagName("body")[0].appendChild(boxModel);
    boxModelVisible = true;
}

看起来他们正在使用标准div + css来绘制它......只需要弄清楚他们现在如何处理事件......(这个文件长28K行)

还有这个片段,我猜测它会找到合适的对象....虽然我无法弄清楚如何。他们正在寻找一个“objectLink-element”类......我不知道这个“repObject”是什么。

onMouseMove: function(event)
{
    var target = event.srcElement || event.target;

    var object = getAncestorByClass(target, "objectLink-element");
    object = object ? object.repObject : null;

    if(object && instanceOf(object, "Element") && object.nodeType == 1)
    {
        if(object != lastHighlightedObject)
        {
            Firebug.Inspector.drawBoxModel(object);
            object = lastHighlightedObject;
        }
    }
    else
        Firebug.Inspector.hideBoxModel();

},

我在想,也许当鼠标移动或鼠标悬停事件为突击显示节点触发时,我可以以某种方式传递它吗?也许节点它覆盖......?


如果我在一个z-index比我的荧光笔更高的元素上面放置一个不可见元素,但是给我的荧光笔提供比实际元素更高的z-index ...理论上,它应该可以工作。隐形元素将触发鼠标事件,但高亮效果仍然看起来像是超出实际元素。

这意味着我只是将DOM元素加倍,并且定位必须正确。 除非,否则我只能“解除”荧光笔目前覆盖的元素?但这可能仍然是每个元素&gt;。&lt;有人帮帮我!

5 个答案:

答案 0 :(得分:25)

所有这些答案都太复杂了......简单的解决方案:

使用Javascript:

prevElement = null;
document.addEventListener('mousemove',
    function(e){
        var elem = e.target || e.srcElement;
        if (prevElement!= null) {prevElement.classList.remove("mouseOn");}
        elem.classList.add("mouseOn");
        prevElement = elem;
    },true);

的CSS:

.mouseOn{
  background-color: #bcd5eb !important;
  outline: 2px solid #5166bb !important;
}

答案 1 :(得分:3)

修改David的答案,以便在之后正确地恢复背景颜色......

$('body *').live('mouseover mouseout', function(event) {
    if (event.type == 'mouseover') {
        $(this).data('bgcolor', $(this).css('background-color'));
        $(this).css('background-color','rgba(255,0,0,.5)');
    } else {
        $(this).css('background-color', $(this).data('bgcolor'));
    }
    return false;
});

答案 2 :(得分:2)

我可以建议一种替代方法吗?

如何简单地将background-color分配给页面的所有子元素,然后在hover()上调整 元素的background-color以增加它的对比?

$('html').children().css('background-color','rgba(0,0,0,0.2)');
$('body').children().hover(
    function(){
        $(this).css('background-color','#fff');
    },
    function(){
        $(this).css('background-color','rgba(0,0,0,0.2)');
    });

JS Fiddle demo

答案 3 :(得分:1)

鼠标悬停后整个页面变红的原因是您的代码与mouseover元素的body事件相匹配。您可以通过仅选择body的孩子来阻止这种情况发生。

$('body *').bind( //...

您将在具有大量元素的页面上遇到性能问题,但是因为bind将为每个匹配的元素附加一个侦听器。试着看一下jQuery的事件委托api(.delegate()http://api.jquery.com/delegate/),它允许你监听传播到根元素的事件,也适用于鼠标事件。

答案 4 :(得分:1)

► This有点不那么烦躁,但是如果没有先完全移动鼠标 off ,那么它无法检测从父元素移动到其中一个子元素。

var $div = $('<div id="highlighter">').css({
    'background-color': 'rgba(255,0,0,.5)',
    'position': 'absolute',
    'z-index': '65535'
}).hide().prependTo('body');

var $highlit;

$('*').live('mousemove', function(event) {
    if (this.nodeName === 'HTML' || this.nodeName === 'BODY')
    {
        $div.hide();
        return false;
    }
    var $this = this.id === 'highligher' ? $highlit : $(this),

        x = event.pageX,
        y = event.pageY,

        width = $this.width(),
        height = $this.height(),
        offset = $this.offset(),

        minX = offset.left,
        minY = offset.top,
        maxX = minX + width,
        maxY = minY + height;

    if (this.id === 'highlighter')
    {
        if (minX <= x && x <= maxX
            && minY <= y && y <= maxY)
        {
            // nada
        }
        else
        {
            $div.hide();
        }
    }
    else
    {
        $highlit = $this;
        $div.offset(offset).width($this.width()).height($this.height()).show();
    }
    return false;
});

希望这有助于让球滚动。您可以调整我写的内容以使用document.elementFromPoint(x, y)来检查鼠标是否已移动到当前突出显示的元素的子元素中。我现在还不清楚这个问题。

或者,如果概述与向您突出显示一样好,您可以尝试我在评论中提到的方法来解决原始问题。在当前悬停的元素周围绘制4个div * - 这是轮廓框每个边缘的一个div。您和实际内容之间不再有绘图元素!


* 我敢打赌document.elementFromPoint(x, y)会让你的鼠标更容易