jQuery 悬停 Alt 标签问题

发布于 2024-12-23 07:54:38 字数 1167 浏览 8 评论 0 原文

我最近问了一个问题,当您将鼠标悬停在图像上时,图像的 alt 标签会显示在图像的中心,幸运的是,我提供了以下代码来执行此操作。

<script type="text/javascript">
    $(document).ready(function () { 
        $('#illustration-content ul li img').hover(
            function(){
                $(this).css('opacity','.2');
                var a = $(this).attr('alt');
                $(this).parent().append('<div class="title">' + a + '</div>');
            },
            function(){
                $(this).css('opacity','1');
                $(this).next().remove('.title');
            }
        );
    });
</script>

这很好用。

我现在遇到的问题是,如果光标在图像中心时移动到 alt 标签上,则会导致整个效果消失。我只希望当光标离开图像时效果消失。

这是我正在使用的 css,html 是直接的 UL 图像列表。

#illustration-content ul li img{
    position: relative;
}

.title{
    position: absolute;
    z-index: 1000;
    width: 100px;
    margin: 80px 0px 0px -150px;
    color: #fff;
    font-size: 18px;
    display: inline-block;
}

我尝试过使用和不使用内联块,结果相同,但标签的位置需要不同。

任何想法为什么会发生这种情况?

以下是问题的示例: http://jsfiddle.net/ysSJu/

感谢您的支持。

I recently asked a question to get the alt tag of an image displayed in the center of the image when you hover over it, and was thankfully provided with this following code to do so.

<script type="text/javascript">
    $(document).ready(function () { 
        $('#illustration-content ul li img').hover(
            function(){
                $(this).css('opacity','.2');
                var a = $(this).attr('alt');
                $(this).parent().append('<div class="title">' + a + '</div>');
            },
            function(){
                $(this).css('opacity','1');
                $(this).next().remove('.title');
            }
        );
    });
</script>

This works great.

The issue I now have is that if the cursor moves over the alt tag when its in the center of the image, it makes the whole effect disappear. I only want the effect to disappear when the cursor leaves the image.

Here is the css I am using and the html is a straight forward UL list of images.

#illustration-content ul li img{
    position: relative;
}

.title{
    position: absolute;
    z-index: 1000;
    width: 100px;
    margin: 80px 0px 0px -150px;
    color: #fff;
    font-size: 18px;
    display: inline-block;
}

I've tried with and without the inline block, same result, but the tag needs to be positions differently.

Any ideas why this may be happening?

Here is an example of the problem: http://jsfiddle.net/ysSJu/

Thanks for any support.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倥絔 2024-12-30 07:54:38

说明

当您将鼠标悬停在标题上时效果消失的原因是因为您只有 img 元素的事件。
相反,您应该将事件“链接”到整个 li,这样当用户将鼠标悬停在列表项上时,整个元素(包括 div.title)都会受到影响。

demonstration

在上图中,您可以看到它是如何工作的。

目前,您的事件已链接到对应于绿色 img 的事件。
这意味着 div.title(黄色)将被视为“外部”元素(因为 div.title 不在 img 元素),因此当您将鼠标悬停在 div.title 上时,mouseleave 事件将会触发。
如果将事件链接到红色li,则该事件将包含红色边框内的所有内容,红色边框为绿色黄色。

您还必须将 li 块视为 display: inline-block ,以便可以相对于图像定位标题。

所以,基本上,我想说的是,而不是

$('#illustration-content ul li img'); 

你应该做的

$('#illustration-content ul li'); 

然后相应地调整代码。


解决方案

这是一个可行的解决方案

var $lis = $('#illustration-content ul li');

$lis.each(function(index, el){
    var $this = $(el);
    var eImg = $("img", $this);

    $this.mouseenter(function(){
        var eTitle = $('<div class="title">' + eImg .attr('alt') + '</div>');
        eImg.css('opacity','.1');
        $this.prepend(eTitle);
    }).mouseleave(function(){
        var eTitle = $("div.title", $this);
        eImg.css('opacity','1');
        eTitle.remove('.title');
    });
});

替代解决方案

与其在每次 mouseenter/mouseleave 处创建和销毁 div,最好在 document.ready() 处生成一次 div,然后显示/隐藏当用户将鼠标悬停在它们上方时它们。
它实际上应该提高整体性能。

这是一个示例。

默认情况下,.title 具有 style 属性显示:无

var $lis = $('#illustration-content ul li');

$lis.each(function(index, el){
    var $this = $(el);
    var eImg = $("img", $this);
    var eTitle = $('<div class="title">' + eImg.attr('alt') + '</div>');

    $this.prepend(eTitle)
        .mouseenter(function(){
            eImg.css('opacity','.1');
            eTitle.show();
        })
        .mouseleave(function(){
            eImg.css('opacity','1');
            eTitle.hide();
        });
});

请注意,

我使用了 mouseenter 和 < a href="http://api.jquery.com/mouseleave/" rel="nofollow noreferrer">mouseleave 而不是 悬停。悬停实际上是这两个事件组合的简写函数。我倾向于使用前者,因为它通常更容易阅读,而且更可靠。

另请注意,在这两种解决方案中,我都使用了函数 .each()
通过将元素分配给变量,JQuery 不必在每次引用节点时浪费更多处理来查找节点;使其更加高效。

通过将元素作为选择器中的第二个参数传递,像这样

$(".title", parent_element).css(...);

我不必使用 .children().next() 。它也非常高效。

您提到您在定位方面遇到了困难,看看这个,它可能会澄清一些事情。


唷,这些长帖子很难读,是吗?嗯,我想我已经涵盖了所需的一切。

祝你好运&快乐编码! :)

Explanation

The reason why the effect disappears when you hover over the title, is because you have the event for the img element only.
Instead, you should "link" the event to the entire li, so that when a user hovers over the list item, the entire element, including the div.title, will be affected.

demonstration

In the above image, you can see how it works.

Currently, you have your events linked to what corresponds to green, img.
This means that the div.title, yellow, will be treated as an "outside" element (because the div.title isn't inside the img element), and therefore the mouseleave event will trigger when you hover over the div.title.
If you link the events to the li, red, the event will encompass everything within the red border, which is green and yellow.

You also have to treat your li blocks as display: inline-block so that you can position the title in relation to the image.

So, basically, what I'm trying to say is, instead of

$('#illustration-content ul li img'); 

you should do

$('#illustration-content ul li'); 

Then adjust the code accordingly.


Solution

Here is a working solution.

var $lis = $('#illustration-content ul li');

$lis.each(function(index, el){
    var $this = $(el);
    var eImg = $("img", $this);

    $this.mouseenter(function(){
        var eTitle = $('<div class="title">' + eImg .attr('alt') + '</div>');
        eImg.css('opacity','.1');
        $this.prepend(eTitle);
    }).mouseleave(function(){
        var eTitle = $("div.title", $this);
        eImg.css('opacity','1');
        eTitle.remove('.title');
    });
});

Alternative solution

Instead of creating and destroying a div at every mouseenter/mouseleave, it might be better to produce the div's just once at document.ready(), and show/hide them when a user hovers over them.
It should actually increase overall performance.

Here's an example.

By default, the .title has the style property display: none.

var $lis = $('#illustration-content ul li');

$lis.each(function(index, el){
    var $this = $(el);
    var eImg = $("img", $this);
    var eTitle = $('<div class="title">' + eImg.attr('alt') + '</div>');

    $this.prepend(eTitle)
        .mouseenter(function(){
            eImg.css('opacity','.1');
            eTitle.show();
        })
        .mouseleave(function(){
            eImg.css('opacity','1');
            eTitle.hide();
        });
});

Additional information, good to know

Note that I used the mouseenter and mouseleave instead of hover. Hover is actually a shorthand function of those two events combined. I tend to use the former, because it is generally easier to read, and more reliable.

Also note that in both solutions, I used the function .each().
By assinging the elements to variables, JQuery won't have to waste more processing to find the nodes every time I reference them; making it more efficient.

By passing an element as a second parameter in the selector, like this

$(".title", parent_element).css(...);

I don't have to use functions like .children() or .next(). It is also very efficient.

You mentioned you had hard time with the positioning, have a look at this, it might clarify things.


Phew, these long posts are hard to read, eh? Well, I think I've covered everything needed.

Good luck & happy coding! :)

赏烟花じ飞满天 2024-12-30 07:54:38

您可以检查 event.latedTarget 属性,看看它是否是 mouseout 函数中的 .title 元素:

            function(event){
                if (!$(event.relatedTarget).hasClass('title')) {
                    $(this).css('opacity','1').siblings().remove();
                }
            }

演示:http://jsfiddle.net/ysSJu/1/

另请注意我如何链接函数调用,这样您就不必制作两个 jQuery 对象这个

更新

我注意到,如果您将光标从一个图像移动到另一个图像,.title 元素将不会像它应该从前一个图像中删除一样。您可以通过重置 img 元素的 opacity.remove() 额外的 .title 元素来解决此问题:

var $images = $('#illustration-content ul li img');
$images.hover(
    function(){
        $images.css('opacity', 1).siblings().remove('.title');
        var $this = $(this),
            a     = $this.attr('alt');
        $this.css('opacity','.2').parent().append('<span class="title">' + a + '</span>');
    },
    function(event){
        if (!$(event.relatedTarget).hasClass('title')) {
            $(this).css('opacity','1').siblings().remove('.title');
        }
    }
);

这是一个演示: http://jsfiddle.net/ysSJu/3/

You can check the event.relatedTarget property to see if it is a .title element in your mouseout function:

            function(event){
                if (!$(event.relatedTarget).hasClass('title')) {
                    $(this).css('opacity','1').siblings().remove();
                }
            }

Demo: http://jsfiddle.net/ysSJu/1/

Also notice how I chained the function calls so you don't have to make two jQuery objects from this.

UPDATE

I noticed that if you move your cursor from one image to another that the .title element will not be removed as it should be from the previous image. You can fix that by resetting the img element's opacity and .remove()ing the extra .title elements:

var $images = $('#illustration-content ul li img');
$images.hover(
    function(){
        $images.css('opacity', 1).siblings().remove('.title');
        var $this = $(this),
            a     = $this.attr('alt');
        $this.css('opacity','.2').parent().append('<span class="title">' + a + '</span>');
    },
    function(event){
        if (!$(event.relatedTarget).hasClass('title')) {
            $(this).css('opacity','1').siblings().remove('.title');
        }
    }
);

Here's a demo: http://jsfiddle.net/ysSJu/3/

醉生梦死 2024-12-30 07:54:38

更改.hover。到 .mouseenter.mouseleave

所以基本上...

var images = $('#illustration-content ul li img');
images.mouseenter(function(){
    $(this).css('opacity','.2');
    var a = $(this).attr('alt');
    $(this).parent().append('<div class="title">' + a + '</div>');
});
images.mouseleave(function(){
    $(this).css('opacity','1');
    $(this).next().remove('.title');
 });

原因是,正如您所指出的,将鼠标悬停在 alt

上会导致悬停事件不再在外部 img 上触发。但是,将 mouseentermouseleave 悬停在 alt

上时,不会触发 mouseleave 的 <代码>

Change .hover. to .mouseenter and .mouseleave.

So basically...

var images = $('#illustration-content ul li img');
images.mouseenter(function(){
    $(this).css('opacity','.2');
    var a = $(this).attr('alt');
    $(this).parent().append('<div class="title">' + a + '</div>');
});
images.mouseleave(function(){
    $(this).css('opacity','1');
    $(this).next().remove('.title');
 });

The reason why is, as you pointed out, hovering over the alt <div> causes the hover event to no longer fire on the outer img. However with mouseenter and mouseleave hovering over the alt <div> doens't fire the mouseleave for the <img>.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文