jQuery动画背景颜色

338

我试图使用jQuery在鼠标悬停时通过动画改变背景颜色。

我查看了一些示例,似乎做得很对,它可以用于其他属性(如fontSize),但是当涉及到backgroundColor时,我会收到一个"无效属性"的js错误。 我正在处理的元素是一个div。

$(".usercontent").mouseover(function() {
    $(this).animate({ backgroundColor: "olive" }, "slow");
});

有什么想法吗?


对于使用jQuery 1.4.2和jQuery Effect 1.8的情况,我不得不承认Andrew的解决方案非常完美。请参见他下面的帖子。 - Patrick Desjardins
1
注意:此插件正在检测元素的当前背景颜色 - 当没有定义背景颜色时,Chrome浏览器返回rgba(0, 0, 0, 0)而不是预期的空/ null值。为了“修复”这个问题,元素必须具有初始背景颜色。 - Shadow The Spring Wizard
链接页面似乎有问题(至少是项目页面和演示页面)。 - Paolo Stefan
18个回答

336

使用颜色插件比使用UI库更节省空间,插件只有4kb。当然,您会想使用可靠的插件版本,而不是一些老旧的有问题的版本,它无法在Safari上处理并在转换速度过快时崩溃。由于没有提供压缩版本,您可以尝试使用各种压缩器和自己制作min版本。在这种情况下,YUI获得了最佳压缩效果,只需要2317个字节,并且因为它非常小 - 这是它的代码:

(function (d) {
    d.each(["backgroundColor", "borderBottomColor", "borderLeftColor", "borderRightColor", "borderTopColor", "color", "outlineColor"], function (f, e) {
        d.fx.step[e] = function (g) {
            if (!g.colorInit) {
                g.start = c(g.elem, e);
                g.end = b(g.end);
                g.colorInit = true
            }
            g.elem.style[e] = "rgb(" + [Math.max(Math.min(parseInt((g.pos * (g.end[0] - g.start[0])) + g.start[0]), 255), 0), Math.max(Math.min(parseInt((g.pos * (g.end[1] - g.start[1])) + g.start[1]), 255), 0), Math.max(Math.min(parseInt((g.pos * (g.end[2] - g.start[2])) + g.start[2]), 255), 0)].join(",") + ")"
        }
    });

    function b(f) {
        var e;
        if (f && f.constructor == Array && f.length == 3) {
            return f
        }
        if (e = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(f)) {
            return [parseInt(e[1]), parseInt(e[2]), parseInt(e[3])]
        }
        if (e = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(f)) {
            return [parseFloat(e[1]) * 2.55, parseFloat(e[2]) * 2.55, parseFloat(e[3]) * 2.55]
        }
        if (e = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(f)) {
            return [parseInt(e[1], 16), parseInt(e[2], 16), parseInt(e[3], 16)]
        }
        if (e = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(f)) {
            return [parseInt(e[1] + e[1], 16), parseInt(e[2] + e[2], 16), parseInt(e[3] + e[3], 16)]
        }
        if (e = /rgba\(0, 0, 0, 0\)/.exec(f)) {
            return a.transparent
        }
        return a[d.trim(f).toLowerCase()]
    }
    function c(g, e) {
        var f;
        do {
            f = d.css(g, e);
            if (f != "" && f != "transparent" || d.nodeName(g, "body")) {
                break
            }
            e = "backgroundColor"
        } while (g = g.parentNode);
        return b(f)
    }
    var a = {
        aqua: [0, 255, 255],
        azure: [240, 255, 255],
        beige: [245, 245, 220],
        black: [0, 0, 0],
        blue: [0, 0, 255],
        brown: [165, 42, 42],
        cyan: [0, 255, 255],
        darkblue: [0, 0, 139],
        darkcyan: [0, 139, 139],
        darkgrey: [169, 169, 169],
        darkgreen: [0, 100, 0],
        darkkhaki: [189, 183, 107],
        darkmagenta: [139, 0, 139],
        darkolivegreen: [85, 107, 47],
        darkorange: [255, 140, 0],
        darkorchid: [153, 50, 204],
        darkred: [139, 0, 0],
        darksalmon: [233, 150, 122],
        darkviolet: [148, 0, 211],
        fuchsia: [255, 0, 255],
        gold: [255, 215, 0],
        green: [0, 128, 0],
        indigo: [75, 0, 130],
        khaki: [240, 230, 140],
        lightblue: [173, 216, 230],
        lightcyan: [224, 255, 255],
        lightgreen: [144, 238, 144],
        lightgrey: [211, 211, 211],
        lightpink: [255, 182, 193],
        lightyellow: [255, 255, 224],
        lime: [0, 255, 0],
        magenta: [255, 0, 255],
        maroon: [128, 0, 0],
        navy: [0, 0, 128],
        olive: [128, 128, 0],
        orange: [255, 165, 0],
        pink: [255, 192, 203],
        purple: [128, 0, 128],
        violet: [128, 0, 128],
        red: [255, 0, 0],
        silver: [192, 192, 192],
        white: [255, 255, 255],
        yellow: [255, 255, 0],
        transparent: [255, 255, 255]
    }
})(jQuery);

2
好的,去Andrew提供的链接。下载文件。你需要将它添加到你的项目中。你仍然可以在你的项目中使用jquery.effects.core,这将完美地工作。感谢你的回答。+1 - Patrick Desjardins
3
我只是将以上内容复制粘贴到我现有的"jquery-ui-1.8.2.min.js"文件中,然后...一切仍然正常工作 :-) - Dave Everitt
7
请注意,作者在去年(2011年)发布了2.0版本的这个插件,其中有很多不错的功能,但这些功能并非基本功能所必需。现在它的大小超过20KB,您可以选择v1分支获取旧版本(仍然有效),且体积更轻巧。 - Aren
6
FWIW - 你可以在代码中删除颜色到rgb的映射并进一步减小大小:https://raw.github.com/gist/1891361/17747b50ad87f7a59a14b4e0f38d8f3fb6a18b27/gistfile1.js 。缺点是你不能为动画使用颜色名称,而必须使用rgb值。 - Niyaz
4
jQuery 1.8 破坏了这个插件。curCSS 不再在 jQuery 中使用。 - Rich Bradshaw
显示剩余8条评论

73

我遇到了同样的问题,并通过引入 jQuery UI 来解决它。下面是完整的脚本:

<!-- include Google's AJAX API loader -->
<script src="http://www.google.com/jsapi"></script>
<!-- load JQuery and UI from Google (need to use UI to animate colors) -->
<script type="text/javascript">
google.load("jqueryui", "1.5.2");
</script>


<script type="text/javascript">
$(document).ready(function() {
$('#menu ul li.item').hover(
    function() {
        $(this).stop().animate({backgroundColor:'#4E1402'}, 300);
        }, function () {
        $(this).stop().animate({backgroundColor:'#943D20'}, 100);
    });
});
</script>

66
使用CSS3过渡效果来实现。支持度很高(所有现代浏览器,甚至包括IE)。借助Compass和SASS,这个操作可以快速完成:
#foo {background:red; @include transition(background 1s)}
#foo:hover {background:yellow}

纯CSS:

#foo {
background:red;
-webkit-transition:background 1s;
-moz-transition:background 1s;
-o-transition:background 1s;
transition:background 1s
}
#foo:hover {background:yellow}

我已经写了一篇关于这个主题的德语文章:http://www.solife.cc/blog/animation-farben-css3-transition.html

6
请在以下网址中调整悬停点击的过渡效果:jsfiddle.net/K5Qyx - Dem Pilafian

32

1
我无法感谢你足够地指出它支持“rgba”,这正是我正在寻找的。 - Onimusha

13

你可以使用jQuery UI添加此功能。你可以只获取需要的内容,例如,如果你想要动画颜色,只需包含以下代码即可。我从最新的jQuery UI(目前为1.8.14)获取了它。

/******************************************************************************/
/****************************** COLOR ANIMATIONS ******************************/
/******************************************************************************/

// override the animation for color styles
$.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
    'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
function(i, attr) {
    $.fx.step[attr] = function(fx) {
        if (!fx.colorInit) {
            fx.start = getColor(fx.elem, attr);
            fx.end = getRGB(fx.end);
            fx.colorInit = true;
        }

        fx.elem.style[attr] = 'rgb(' +
            Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
            Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
            Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
    };
});

// Color Conversion functions from highlightFade
// By Blair Mitchelmore
// http://jquery.offput.ca/highlightFade/

// Parse strings looking for color tuples [255,255,255]
function getRGB(color) {
        var result;

        // Check if we're already dealing with an array of colors
        if ( color && color.constructor == Array && color.length == 3 )
                return color;

        // Look for rgb(num,num,num)
        if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
                return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];

        // Look for rgb(num%,num%,num%)
        if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
                return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

        // Look for #a0b1c2
        if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
                return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

        // Look for #fff
        if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
                return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

        // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
        if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
                return colors['transparent'];

        // Otherwise, we're most likely dealing with a named color
        return colors[$.trim(color).toLowerCase()];
}

function getColor(elem, attr) {
        var color;

        do {
                color = $.curCSS(elem, attr);

                // Keep going until we find an element that has color, or we hit the body
                if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
                        break;

                attr = "backgroundColor";
        } while ( elem = elem.parentNode );

        return getRGB(color);
};

使用 YUI 压缩后,它的大小仅为 1.43kb:

$.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","borderColor","color","outlineColor"],function(b,a){$.fx.step[a]=function(c){if(!c.colorInit){c.start=getColor(c.elem,a);c.end=getRGB(c.end);c.colorInit=true}c.elem.style[a]="rgb("+Math.max(Math.min(parseInt((c.pos*(c.end[0]-c.start[0]))+c.start[0],10),255),0)+","+Math.max(Math.min(parseInt((c.pos*(c.end[1]-c.start[1]))+c.start[1],10),255),0)+","+Math.max(Math.min(parseInt((c.pos*(c.end[2]-c.start[2]))+c.start[2],10),255),0)+")"}});function getRGB(b){var a;if(b&&b.constructor==Array&&b.length==3){return b}if(a=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(b)){return[parseInt(a[1],10),parseInt(a[2],10),parseInt(a[3],10)]}if(a=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(b)){return[parseFloat(a[1])*2.55,parseFloat(a[2])*2.55,parseFloat(a[3])*2.55]}if(a=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(b)){return[parseInt(a[1],16),parseInt(a[2],16),parseInt(a[3],16)]}if(a=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(b)){return[parseInt(a[1]+a[1],16),parseInt(a[2]+a[2],16),parseInt(a[3]+a[3],16)]}if(a=/rgba\(0, 0, 0, 0\)/.exec(b)){return colors.transparent}return colors[$.trim(b).toLowerCase()]}function getColor(c,a){var b;do{b=$.curCSS(c,a);if(b!=""&&b!="transparent"||$.nodeName(c,"body")){break}a="backgroundColor"}while(c=c.parentNode);return getRGB(b)};

您也可以使用CSS3转换来实现颜色动画效果,但这仅受到现代浏览器的支持。

a.test {
  color: red;
  -moz-transition-property: color;  /* FF4+ */
  -moz-transition-duration: 1s;
  -webkit-transition-property: color;  /* Saf3.2+, Chrome */
  -webkit-transition-duration: 1s;
  -o-transition-property: color;  /* Opera 10.5+ */
  -o-transition-duration: 1s;
  -ms-transition-property: color;  /* IE10? */
  -ms-transition-duration: 1s;
  transition-property: color;  /* Standard */
  transition-duration: 1s;
  }

  a.test:hover {
  color: blue;
  }

使用属性缩写:

/* shorthand notation for transition properties */
/* transition: [transition-property] [transition-duration] [transition-timing-function] [transition-delay]; */

a.test {
  color: red;
  -moz-transition: color 1s;
  -webkit-transition: color 1s;
  -o-transition: color 1s;
  -ms-transition: color 1s;
  transition: color 1s;
  }

a.test {
  color: blue;
 }

CSS3 过渡动画经过硬件加速,比普通的 JavaScript 过渡动画更加流畅。你可以使用 Modernizr 来检查浏览器是否支持 CSS3 过渡动画,如果不支持,则可以使用 jQuery 作为后备方案:

if ( !cssTransitions() ) {
    $(document).ready(function(){
        $(".test").hover(function () {
                $(this).stop().animate({ backgroundColor: "red" },500)
             }, function() {
                 $(this).stop().animate({ backgroundColor: "blue" },500)}    
             );
    }); 
}

记得在开始新动画之前使用stop()停止当前动画,否则当您在元素上快速移动时,效果会持续闪烁一段时间。


11

对于任何需要这个的人。最好使用jQuery UI版本,因为它适用于所有浏览器。颜色插件在Safari和Chrome上存在问题。它只能有时候工作。


6
最新版本的颜色插件在Chrome中运行完美。 - Andrew
3
仅为了实现背景动画而添加额外脚本会使页面变得较为沉重。 - oneiros

11

你可以使用两个div:

在原来的div上面放一个克隆的div,在淡出原始div的同时淡入克隆div。

当淡入淡出效果完成后,用新的背景恢复原始div。

$(function(){
    var $mytd = $('#mytd'), $elie = $mytd.clone(), os = $mytd.offset();

      // Create clone w other bg and position it on original
    $elie.toggleClass("class1, class2").appendTo("body")
         .offset({top: os.top, left: os.left}).hide();

    $mytd.mouseover(function() {            
          // Fade original
        $mytd.fadeOut(3000, function() {
            $mytd.toggleClass("class1, class2").show();
            $elie.toggleClass("class1, class2").hide();            
        });
          // Show clone at same time
        $elie.fadeIn(3000);
    });
});​

jsFiddle实例


.toggleClass()
.offset()
.fadeIn()
.fadeOut()


也许它在某个时候可以工作,但至少现在它似乎没有达到预期的效果。 - epeleg
@epeleg - 对我来说,在Mac Chrome上可以工作。您点击彩色矩形,它就会改变颜色(2013-07-15)。 - Peter Ajtai
我不知道为什么,但是它现在在我的Windows7 Chrome上可以工作了。也许与我昨天进行的Chrome更新有关?无论如何,正如我所说的,现在确实可以工作了。 - epeleg

8
我使用了CSS过渡和JQuery的组合来实现所需效果。显然,不支持CSS过渡的浏览器将不会进行动画处理,但这是一个轻量级选项,在大多数浏览器上都能很好地运行,并且对于我的要求而言,可以接受这种退化情况。
使用JQuery来更改背景颜色:
   $('.mylinkholder a').hover(
        function () {
            $(this).css({ backgroundColor: '#f0f0f0' }); 
        },
        function () {
            $(this).css({ backgroundColor: '#fff' });
        }
    );

使用CSS的过渡效果来实现背景颜色的淡入淡出切换。
   .mylinkholder a
   {
   transition: background-color .5s ease-in-out;
   -moz-transition: background-color .5s ease-in-out;
   -webkit-transition: background-color .5s ease-in-out; 
  -o-transition: background-color .5s ease-in-out; 
   }

6

请将示例内联,以避免链接失效。 - Ege Özcan

6
这些天,jQuery颜色插件支持以下命名颜色:
aqua:[0,255,255],
azure:[240,255,255],
beige:[245,245,220],
black:[0,0,0],
blue:[0,0,255],
brown:[165,42,42],
cyan:[0,255,255],
darkblue:[0,0,139],
darkcyan:[0,139,139],
darkgrey:[169,169,169],
darkgreen:[0,100,0],
darkkhaki:[189,183,107],
darkmagenta:[139,0,139],
darkolivegreen:[85,107,47],
darkorange:[255,140,0],
darkorchid:[153,50,204],
darkred:[139,0,0],
darksalmon:[233,150,122],
darkviolet:[148,0,211],
fuchsia:[255,0,255],
gold:[255,215,0],
green:[0,128,0],
indigo:[75,0,130],
khaki:[240,230,140],
lightblue:[173,216,230],
lightcyan:[224,255,255],
lightgreen:[144,238,144],
lightgrey:[211,211,211],
lightpink:[255,182,193],
lightyellow:[255,255,224],
lime:[0,255,0],
magenta:[255,0,255],
maroon:[128,0,0],
navy:[0,0,128],
olive:[128,128,0],
orange:[255,165,0],
pink:[255,192,203],
purple:[128,0,128],
violet:[128,0,128],
red:[255,0,0],
silver:[192,192,192],
white:[255,255,255],
yellow:[255,255,0]

1
请问您能否提供出处?顺便感谢您的列表。 - sharat87
这个列表来自于jQuery颜色插件:http://plugins.jquery.com/project/color - spoulson
2
您的颜色列表是过时的版本。当前版本至少有一种额外的颜色,我注意到了。 - Andrew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接