在用linear-gradient设置彩虹般的背景时,忽然想到如果能让它们流动起来一定更好看。在网上搜了一波后发现并没有别人提出这个想法并实现,于是便自己着手写了起来。
代码见Github - colorful-linear-animate
颜色变化原理
一开始想到的当然是Jquary-ui里的颜色animate,但似乎没什么方法可以把那种变化移植到linear的多彩背景变化中来。
于是首先要弄清楚颜色之间相互转换时它们的rgb是怎样变化的。
因为我要制造的是七彩的变化,可以看到跟常见的rgb选框中右边的颜色条是一样的:
于是拉动颜色条观察rgb数值,发现从底下的红色一直变化到最上面回到红色的过程中,rgb是以green-blue-red的方向在变化的,每次变化为左边的颜色并将之替换。
例如上图里一开始是#ff8181,在进度条往上拉动的过程中,中间的green色81一直增加至左边的ff,一直变化到#ffff81,接着左边的ff就一直减少至#81ff81,如此类推,之后是#8181ff,最后再回到#ff8181。
实现方法
根据颜色的变化方式,即可把linear-gradient分为6个节点,恰好每次增加20%,即一开始的linear-gradient值为
(#ff8181 0%, #ffff81 20%, #81ff81 40%, #81ffff 60%, #8181ff 80%, #ff81ff 100%)
如此从100%那下一个变化的颜色是#ff8181,即回到了0%的颜色,呈现出来是这样的:
接着最重要的来了,如何让它动起来呢?
我的实现方法是,让linear各个节点的颜色不断变化到下一个颜色(最后一个即变化到第一个),即在setInterval里让各个节点的rgb数值+1或-1变化,一直变化到下一个颜色,之后再继续变化到下一个颜色。
通俗说起来就是各个颜色层之间总在追赶着下一个颜色层,这样循环反复,即实现了流动变化的效果。
最终写出来的代码参见github,用户还可自由控制颜色的鲜艳度、方向、变化速度。
代码:
| /* | |
| * 七彩背景颜色并不断动态变化 | |
| * element: 选择器 | |
| * colorful: 颜色鲜艳度 (从ff-00越来越鲜艳,ff为一片空白) | |
| * angle: 角度 (to top, to bottom, to left, to right, 135deg, to top right...) | |
| * speed: 变化速度 (slow, normal, fast) | |
| */ | |
| function colorfulAnimate(element, colorful, angle, speed) | |
| { | |
| //缺省参数 | |
| element = element || "body"; | |
| colorful = colorful || "bb"; | |
| angle = angle || "to top"; | |
| speed = speed || "normal"; | |
| //变化速度 | |
| var speedNum = {'slow': 100, 'normal': 60, 'fast': 20}; | |
| //构建各层次的rgb | |
| var colorNum = parseInt(colorful, 16); | |
| var c = [ | |
| [256, colorNum, colorNum], | |
| [256, 256, colorNum], | |
| [colorNum, 256, colorNum], | |
| [colorNum, 256, 256], | |
| [colorNum, colorNum, 256], | |
| [256, colorNum, 256] | |
| ]; | |
| //各层次的下一个变化颜色 | |
| var c2be = $.extend(true, [], c); | |
| changeC2be(); | |
| //颜色动态变化 | |
| function colorAnimate() | |
| { | |
| //时刻检测调整html大小(防止DOM高度小于浏览器窗口时,linear-gradient在firefox的bug) | |
| if ($("html").height() < $(document).height()) | |
| $("html").height($(document).height()); | |
| //这个c2be已经完成,更新 | |
| if (c[0].toString() == c2be[0].toString()) | |
| changeC2be(); | |
| //变化c到下一个数值 | |
| for (var i=0; i<6; i++) | |
| c[i] = c2next(c[i], c2be[i]); | |
| //更新css | |
| var linear = "linear-gradient(" + angle; | |
| for (var i=0; i<6; i++) | |
| linear += ", rgb(" + c[i][0] + ", " + c[i][1] + ", " + c[i][2] + ") " + i*20 + "%"; | |
| linear += ")"; | |
| $(element).css("background", linear); | |
| } | |
| setInterval(function() {colorAnimate();}, speedNum[speed]); | |
| //颜色值加减 | |
| function c2next(orig, next) | |
| { | |
| for (var i=0; i<3; i++) | |
| { | |
| if (orig[i] != next[i]) | |
| { | |
| if (orig[i] > next[i]) | |
| orig[i]--; | |
| else | |
| orig[i]++; | |
| break; | |
| } | |
| } | |
| return orig; | |
| } | |
| //更新下一个变化颜色 | |
| function changeC2be() | |
| { | |
| c2be.push(c2be.shift()); | |
| } | |
| } |