使用jQuery单击时保持图像悬停按钮

时间:2011-10-04 12:29:23

标签: jquery image hover

当我将鼠标悬停在按钮图像上时,我有以下代码来提供悬停效果:

 $("img.hoverImage")
    .mouseover(function () {
        var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
        $(this).attr("src", src);
    })
    .mouseout(function () {
        var src = $(this).attr("src").replace("_hover", "");
        $(this).attr("src", src);
    });

这很有效。我现在有一个额外的要求:

我连续三个按钮都有class =“hoverImage”。

<a class="imageLink" href=""><img class="hoverImage" src="/Content/Images/1.png"/></a>
<a class="imageLink" href=""><img class="hoverImage" src="/Content/Images/2.png"/></a>
<a class="imageLink" href=""><img class="hoverImage" src="/Content/Images/3.png"/></a>

我仍然希望保持这种悬停效果,但现在我也想更改它,所以当我点击图像时,它会保持显示悬停图像(即使我将鼠标移出该图像)。当我点击另一个按钮时,它应该从其他按钮中移除悬停。

注意:点击图片链接不会重定向到新页面(他们只是从js文件中调用一些ajax)

使用jQuery扩展以下代码以支持此功能的最佳方法是什么?看来我需要在单击项目后禁用mouseout处理程序,但我试图避免使用复杂的解决方案。

10 个答案:

答案 0 :(得分:10)

您可以使用class / data / attr之一跟踪点击图像的活动状态,这样就可以完成工作。

$("img.hoverImage").mouseover(function(){
  if ($(this).is('.activeImage')) return;
  var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
  $(this).attr("src", src);
}).mouseout(function(){
  if ($(this).is('.activeImage')) return; // Skip mouseout for active image
  var src = $(this).attr("src").replace("_hover", "");
  $(this).attr("src", src);
}).click(function(){
  // remove previous active state
  $('.activeImage').not(this).removeClass('activeImage').trigger('mouseout');
  // set new active state
  $(this).addClass('activeImage');
  return false;
});

答案 1 :(得分:3)

$("img.hoverImage").click(function() {
    $(this).removeClass("hoverImage").addClass("keepImage");
    $(this).siblings("img.keepImage").removeClass("keepImage").addClass("hoverImage");
});

基本上,您在单击时删除了hoverimage类及其功能,因此当您将鼠标移出时不会发生mouseout事件。它还将hoverImage类恢复为所有兄弟姐妹。

你仍然可能需要在我的点击处理程序中恢复兄弟姐妹的非悬停图像。

编辑:我让你成为一个JSFiddle,我采取了不同的方法:

http://jsfiddle.net/jqWJN/2/

基本上,你使用类hoverImage建立一些链接,如下所示:

<a class="hoverImage"> </a>

然后,您将它们声明为内嵌块,其宽度和高度与图像的宽度和高度相匹配,并为它们提供您选择的背景图像:

a.hoverImage {
    display: inline-block;
    width: 100px; height: 100px;
    background-image: url(http://placekitten.com/g/100/100);
}

然后,你创建一个CSS属性,当它们悬停时为它们提供一个新的背景图像,当它们有“keepImage”类时:

a.hoverImage:hover, a.hoverImage.keepImage {
    background-image: url(http://placekitten.com/100/100);
}

当然,如果你想要不同的照片,你必须为每个链接制作一个独特的链接。

最后,你创建了一小段JQuery,它们在点击时会向它们添加类keepImage,并从拥有它的兄弟姐妹中删除该类:

$("a.hoverImage").click(function() {
    $(this).siblings(".keepImage").removeClass("keepImage");
    $(this).addClass("keepImage");
});

如果您希望这个工作范围更广,而不仅仅是一组兄弟姐妹,比如说,在页面范围内,只需替换它:

$(this).siblings(".keepImage")

用这个:

$(".keepImage")
祝你好运!

答案 2 :(得分:2)

我认为如果你使用带有图像作为背景的“div”会更容易。指定div宽度和高度与背景图像相同并应用它。 这特别适用于您使用这些图像作为占位符以便用户点击它的情况。

更改后,请指定:hover CSS fix。 您拥有的新要求与识别当前活动图像有关。 为此,

     $("<<placeholder - selector>>").click(function(){
           $(this).addClass("active").siblings().removeClass("active");

     });

如果兄弟姐妹中已存在活动课程,则会将其删除,并突出显示当前课程。希望这能解决问题

答案 3 :(得分:2)

我个人会做出很多改变:

首先,我不会依赖交换文件名块的逻辑。您可能希望稍后更改您的约定,并且不希望必须通过JavaScript更正内容。我会按照以下几点做点什么:

<img src="/Content/Images/1.png"
     data-active-image="/Content/Images/1_hover.png" />

如果将来你想扩展它,天空是极限:

<img src="/Content/Images/1.png"
     data-active-image="/Content/Images/1_hover.png"
     data-hover-image="/Content/Images/1_hover.png"
     data-disabled-image="/Content/Images/1_hover.png" />

其次,我会把事情搞清楚。我会有事件代码,然后是图像选择代码。这是我为图像选择代码放在一起的内容:

$.fn.updateImage = function(hovering) {
    return this.each(function() {
        var $el = $(this);
        var active = (hovering || $el.hasClass('active'));

        var image = active ? 'activeImage' : 'inactiveImage';

        if(!$el.data('inactiveImage'))
            $el.data('inactiveImage', $el.attr('src'));

        $el.attr('src', $el.data(image));
    });
};

它接受来自事件代码的布尔值,以表示鼠标是否结束。它会检查元素是否具有活动类。如果它具有活动类,或者正在悬停,则为true。我们使用它来选择使用哪个来源。下一位用于在data-inactive-image属性中缓存原始源。最后,我们设置了源。

接下来我们有事件代码。由于我们正在处理一种无线电按钮样式分组,我会将其分解,因此每页可以有多个图像组。点击后,我们将原始选择器中的所有图像设为非活动状态,并使用前面提到的active类激活当前图像:

$.fn.makeHoverGroup = function() {
    var $group = this;

    return this
        .mouseover(function() {
            $(this).updateImage(true);
        })
        .mouseout(function() {
            $(this).updateImage(false);
        })
        .click(function() {
            $group.not(this).removeClass('active').updateImage(false);
            $(this).addClass('active').updateImage(true);
        });
};

要将它们连接在一起,我们只剩下一行:

$('.hoverImage').makeHoverGroup();

作为一个额外的好处,CSS知道JavaScript所做的一切。 Hovered图像具有.hoverImage:hover选择器(IE6支持a:hover .hoverImage),活动图像具有.hoverImage.active选择器。

您可以在此处查看示例:http://fiddle.jshell.net/nDdzA/1/

更新修复了点击后删除/重新添加的问题。

答案 4 :(得分:1)

以下是有关如何实现目标的示例代码:http://jsfiddle.net/wCL2g/

javascript代码:

$("img.hoverImage").mouseover(function() {

    var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
    $(this).attr("src", src);

    // add class to state the element is hovered
    $(this).addClass('hover');
}).mouseout(function() {
    // don't trigger this function if element has clicked state
    if ($(this).hasClass('click')) {
        return;
    }

    var src = $(this).attr("src").replace("_hover", "");
    $(this).attr("src", src);

    // remove hover class
    $(this).removeClass('hover');
}).click(function(e) {
    // disable the default click event
    e.preventDefault();

    $(this).parent()              // from the parent element
           .siblings()            // find all the siblings elements <a>'s
           .find('img')           // find <img> inside each sibling
           .removeClass('hover')  // remove hover class
           .removeClass('click'); // remove click class

    // trigger the mouse over event for the image tag
    $(this).addClass('click').trigger('mouseover');
});

希望这有帮助

答案 5 :(得分:1)

为了便于阅读,我已将事件处理程序的工作转换为函数。这可能会在生产代码中稍微清理一下,但对于这么大的东西来说这是一个小问题。

单击一个元素后,它将获得“isClicked”类,其余部分将其删除。所有匹配的元素都传递给unHover函数。 unHover函数与mouseout处理函数相同,只是它只适用于缺少isClicked类的元素。

$("img.hoverImage")
    .mouseover(function () {
        makeHoverImage(this);
    })
    .mouseout(function () {
        unHoverImage(this);
    })
    .click(function(){
        makeActive(elem);
    });

function makeActive(elem){
    $("img.hoverImage").removeClass("isClicked");
    $(elem).addClass("isClicked");
    $("img.hoverImage").each(function(index,elem){
        unHoverImage(elem);
    });
}

function makeHoverImage(elem){
    var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
    $(this).attr("src", src);
}

function unHoverImage(elem){
    if (!$(elem).hasClass("isClicked")){
        var src = $(this).attr("src").replace("_hover", "");
        $(this).attr("src", src);
    }
}

答案 6 :(得分:1)

我会设置一个存储当前图像src的全局字符串。然后在mouseout函数中使用它来测试是否已单击当前图像,如果是,则跳过通常的mouseout过程。

在鼠标单击时,该函数查找src为currentImage的图像,在找到currentImage变量后重置该变量(允许mouseout函数正确运行)并手动执行mouseout。然后它将currentImage变量设置为图像src(如上所述)。

此解决方案也很方便,因为它适合您的队列,对JS的影响最小,对CSS和HTML没有影响。

如果您有任何疑问,请查看以下代码并告诉我们:)

var currentImage = "0";

$("img.hoverImage")
.click(function(){
    $("img.hoverImage").each(function() {
        if($(this).attr("src")==currentImage){
            currentImage = "0";
            $(this).mouseout();
        }
    });
    currentImage = $(this).attr("src");
})
.mouseover(function () {
    var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
    $(this).attr("src", src);
})
.mouseout(function () {
    if($(this).attr("src") != currentImage){
        var src = $(this).attr("src").replace("_hover", "");
        $(this).attr("src", src);
    }
});

谢谢! :)

答案 7 :(得分:0)

使用jquery mousedown&amp; mouseup

$("img.hoverImage")
.mouseenter(function () {
    var src = $(this).attr("src").match(/[^\.]+/) + "_hover.png";
    $(this).attr("src", src);
})
.mouseleave(function () {
    var src = $(this).attr("src").replace("_hover", "");
    $(this).attr("src", src);
});
.mousedown(function () {
   $(this).trigger('mouseleave');
})
.mouseup(function () {
     $(this).trigger('mouseenter');
});

答案 8 :(得分:0)

许多人建议为此使用jQuery属性和元数据处理。在这里,我建议使用全局变量。但是,您可能遇到的问题很少,所以让我解释一下解决方案:

(1)。如果你输入一个全局变量,请注意锚点中的href =“”。如果您触发重新加载页面,则返回方形零,不好。所以我删除了它。

(2)。您想要在mouseover和mouseout中检查全局变量以执行类似

的操作
if <triggered from current> return;   // disabling check    

问题是在点击功能中你想要做类似

的事情
if <there is a current> current.trigger('mouseout');
<set new current>
current.trigger('mouseover')

但是由于我们通过禁用检查禁用鼠标输出和鼠标悬停,然后触发这些不起作用。

这里有两个选项:a)你可以将current设置为null,触发这两个事件,然后将当前设置为单击的一个; b)或者您可以将触发器的过/关效果隔离开来,这样您就可以在两个地方调用它。

选项(a)是一个更复杂的点击处理程序,但更简单的鼠标处理程序。选项(b)只需要更多的重构,但如果您更喜欢使用其他jQuery功能,那么这可能是一个好主意。

(3)。因为我不使用jQuery惯用语而是你的方法,所以需要小心使用正则表达式,以便它与应有的匹配。我这样做了。

(4)。下面的代码将点击附加到锚点,如您所提到的(尽管有些解决方案提到了图像本身。)这里的问题是如何将点击的对象链接到相应的图像。在下面的代码中,jQuery的 find()是线索。

(5)。在jQuery中最好不要使用全局变量,即窗口对象级别的变量。您仍然可以获得相同的结果,声明变量高于所涉及的闭包,如下所示。此外,人们喜欢使用$来保存包含jQuery包装对象的变量,我这样做了。

(6)。最后,要注意对象比较。下面的代码确保我们比较DOM对象,所以使用jQuery的 get()

所以,这是修改后的HTML(删除了href):

<a id="anchor1" class="imageLink" ><img class="hoverImage" src="images/1.png"/></a>
<a id="anchor2" class="imageLink" ><img class="hoverImage" src="images/2.png"/></a>
<a id="anchor3" class="imageLink" ><img class="hoverImage" src="images/3.png"/></a>

(抱歉,图片网址不是你的,我实际上测试了下面的代码)

方法(a):

<script type="text/javascript">
$(function() {
    var clickedImg = null; // this is common to all closures below
    $("img.hoverImage")
        .mouseover(function () {
            var $img = $(this);
            if ($img.get(0) == clickedImg) return;
            // note the improved matching !
            var src = $img.attr("src").match(/[^_\.]+/) + "_hover.png"; 
            $img.attr("src", src);
        })
        .mouseout(function () {
            var $img = $(this);
            if ($img.get(0) == clickedImg) return;
            var src = $img.attr("src").replace("_hover","");
            $img.attr("src", src);
        });
         $("a.imageLink").click(function() {
            var oldClicked = clickedImg;
            clickedImg = null;                         // set to null to trigger events
            if (oldClicked) $(oldClicked).mouseout();
            var newClicked = $(this).find('img').get(0);
            $(newClicked).mouseover();
            clickedImg = newClicked;                   // redefine at the end

            alert($(this).attr('id') + " clicked"); // ajax call here
            });
});
</script>

和方法(b):

<script type="text/javascript">
$(function() {
   var clickedImg = null; // same global
   // refactor the mouse over/out - you could use other jQuery ways here
   function doOver($img) {
       var src = $img.attr("src").match(/[^_\.]+/) + "_hover.png";
       $img.attr("src", src);
   }
   function doOut($img) {
       var src = $img.attr("src").replace("_hover","");
       $img.attr("src", src);
   }
   $("img.hoverImage")
        .mouseover(function () {
                var $img = $(this);
                if ($img.get(0) == clickedImg) return;
                doOver($img);
        })
        .mouseout(function () {
                var $img = $(this);
                if ($img.get(0) == clickedImg) return;
                doOut($img);
        });
   $("a.imageLink").click(function() {
        if (clickedImg) doOut($(clickedImg));
        clickedImg = $(this).find('img').get(0);
        doOver($(clickedImg));
        alert($(this).attr('id') + " clicked"); // presumably your ajax call here
   });
});
</script>

选项(a)保留了您的结构,但我认为选项(b)应该是您的下一步,这是我的偏好。

答案 9 :(得分:-3)

如果您的链接没有更改窗口位置,您可以继续使用Andreas的答案或类似的东西。如果他们这样做,它看起来更像是服务器端脚本的工作。我不知道你使用的是哪一个,所以我将在php中发布一个例子。

<?php foreach ($links as $i => $link): ?>
<a class="imageLink" href="<?php echo $link ?>">
  <img class="hoverImage" src="/Content/Images/<?php echo ($i == $selected) ? $i . "_hover" : $i ?>.png"/>
</a>
<?php endforeach ?>