JavaScript 颜色梯度和渐变效果

实例效果

<script type="text/javascript"><!-- var $$ = function (id) { return "string" == typeof id ? document.getElementById(id) : id; }; var Extend = function(destination, source) { for (var property in source) { destination[property] = source[property]; } return destination; } var Map = function(array, callback, thisObject){ if(array.map){ return array.map(callback, thisObject); }else{ var res = []; for (var i = 0, len = array.length; i < len; i++) { res.push(callback.call(thisObject, array[i], i, array)); } return res; } } var ColorGrads = function(options){ this.SetOptions(options); this.StartColor = this.options.StartColor; this.EndColor = this.options.EndColor; this.Step = Math.abs(this.options.Step); }; ColorGrads.prototype = { //设置默认属性 SetOptions: function(options) { this.options = {//默认值 StartColor: "#fff",//开始颜色 EndColor: "#000",//结束颜色 Step: 20//渐变级数 }; Extend(this.options, options || {}); }, //获取渐变颜色集合 Create: function() { var colors = [], startColor = this.GetColor(this.StartColor), endColor = this.GetColor(this.EndColor), stepR = (endColor[0] - startColor[0]) / this.Step, stepG = (endColor[1] - startColor[1]) / this.Step, stepB = (endColor[2] - startColor[2]) / this.Step; //生成颜色集合 for(var i = 0, n = this.Step, r = startColor[0], g = startColor[1], b = startColor[2]; i < n; i++){ colors.push([r, g, b]); r += stepR; g += stepG; b += stepB; } colors.push(endColor); //修正颜色值 return Map(colors, function(x){ return Map(x, function(x){ return Math.min(Math.max(0, Math.floor(x)), 255); });}); }, //获取颜色数据 GetColor: function(color) { if(/^#[0-9a-f]{6}$/i.test(color)) {//#rrggbb return Map([color.substr(1, 2), color.substr(3, 2), color.substr(5, 2)], function(x){ return parseInt(x, 16); } ) } else if(/^#[0-9a-f]{3}$/i.test(color)) {//#rgb return Map([color.substr(1, 1), color.substr(2, 1), color.substr(3, 1)], function(x){ return parseInt(x + x, 16); } ) } else if(/^rgb(.*)$/i.test(color)) {//rgb(n,n,n) or rgb(n%,n%,n%) return Map(color.match(//d+(/./d+)?/%?/g), function(x){ return parseInt(x.indexOf("%") > 0 ? parseFloat(x, 10) * 2.55 : x, 10); } ) } else {//color var mapping = {"red":"#FF0000"};//略 color = mapping[color.toLowerCase()]; if(color){ return Map([color.substr(1, 2), color.substr(3, 2), color.substr(5, 2)], function(x){ return parseInt(x, 16); } ) } } } }; var CurrentStyle = function(element){ return element.currentStyle || document.defaultView.getComputedStyle(element, null); } var Bind = function(object, fun) { var args = Array.prototype.slice.call(arguments).slice(2); return function() { return fun.apply(object, args.concat(Array.prototype.slice.call(arguments))); } } //渐变对象 var ColorTrans = function(obj, options){ this._obj = $$(obj); this._timer = null;//定时器 this._index = 0;//索引 this._colors = [];//颜色集合 this._grads = new ColorGrads(); this.SetOptions(options); this.Speed = Math.abs(this.options.Speed); this.CssColor = this.options.CssColor; this._startColor = this.options.StartColor || CurrentStyle(this._obj)[this.CssColor]; this._endColor = this.options.EndColor; this._step = Math.abs(this.options.Step); this.Reset(); this.SetColor(); }; ColorTrans.prototype = { //设置默认属性 SetOptions: function(options) { this.options = {//默认值 StartColor: "",//开始颜色 EndColor: "#000",//结束颜色 Step: 20,//渐变级数 Speed: 20,//渐变速度 CssColor: "color"//设置属性(Scripting属性) }; Extend(this.options, options || {}); }, //重设颜色集合 Reset: function(color) { //修改颜色后必须重新获取颜色集合 color = Extend({ StartColor: this._startColor, EndColor: this._endColor, Step: this._step }, color || {}); //设置属性 this._grads.StartColor = this._startColor = color.StartColor; this._grads.EndColor = this._endColor = color.EndColor; this._grads.Step = this._step = color.Step; //获取颜色集合 this._colors = this._grads.Create(); this._index = 0; }, //颜色渐入 FadeIn: function() { this.Stop(); this._index++; this.SetColor(); if(this._index < this._colors.length - 1){ this._timer = setTimeout(Bind(this, this.FadeIn), this.Speed); } }, //颜色渐出 FadeOut: function() { this.Stop(); this._index= this._index-1 ; this.SetColor(); if(this._index > 0){ this._timer = setTimeout(Bind(this, this.FadeOut), this.Speed); } }, //颜色设置 SetColor: function() { var color = this._colors[Math.min(Math.max(0, this._index), this._colors.length - 1)]; this._obj.style[this.CssColor] = "rgb(" + color[0] + "," + color[1] + "," + color[2] + ")"; }, //停止 Stop: function() { clearTimeout(this._timer); } }; // --></script>

预览效果1:

这是一个颜色梯度变化演示:

<!-- #idGrads{} #idGrads div{ font-size:0;height:1px;} -->

<script type="text/javascript"><!-- var forEach = function(array, callback, thisObject){ if(array.forEach){ array.forEach(callback, thisObject); }else{ for (var i = 0, len = array.length; i < len; i++) { callback.call(thisObject, array[i], i, array); } } } var colors = new ColorGrads({ StartColor: "#fff", EndColor: "rgb(20,127,0)" }).Create(); forEach(colors.concat().concat(colors.reverse()), function(x){ $$("idGrads").innerHTML += "<div st"+"yle=/"background-color:"+"rgb(" + x[0] + "," + x[1] + "," + x[2] + ");/"></div>"; }) // --></script>


预览效果2:

一个颜色渐变的菜单:

<!-- #idMenu{ background:#DBDBDB;text-align:center;line-height:25px; table-layout:fixed;} #idMenu td{ cursor:pointer;} -->

CropperTweenSliderResizeDrag

<script type="text/javascript"><!-- forEach($$("idMenu").getElementsByTagName("td"), function(x, i){ var ct1 = new ColorTrans(x, { StartColor: "#666", EndColor: "#fff" }); var ct2 = new ColorTrans(x, { StartColor: "#f6f6f6", EndColor: "rgb(20,150,0)", CssColor: "backgroundColor" }); x.onmouseover = function(){ ct1.FadeIn(); ct2.FadeIn(); } x.onmouseout = function(){ ct1.FadeOut(); ct2.FadeOut(); } }) // --></script>


预览效果3:

颜色渐变的有趣应用,点击随机颜色渐变:

点击随机换颜色

<script type="text/javascript"><!-- var ctRandom = new ColorTrans("idRandom", { EndColor: "#CCC", CssColor: "backgroundColor" }) $$("idRandom").onclick = function(){ var rgb = Map([1,1,1], function(){ return Math.floor((Math.random() * 255)); } ); ctRandom.Reset({ StartColor: this.style.backgroundColor, EndColor: "rgb(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + ")" }) ctRandom.FadeIn(); } // --></script>

 

程序说明

【ColorGrads颜色梯度】

程序ColorGrads的作用是通过StartColor和EndColor生成颜色梯度集合。
颜色都可以用红(r)、绿(g)、蓝(b)三个颜色来表示。
程序中先通过GetColor把一般的颜色表示形式转化成一个用红(r)、绿(g)、蓝(b)三个颜色值作元素的集合。
那就首先要知道有什么颜色表示形式,从w3c的Colors部分 可以知道有以下形式:
关键词模式:
em { color: red }
RGB颜色模式:
em { color: #f00 }
em { color: #ff0000 }
em { color: rgb(255,0,0) }     
em { color: rgb(100%, 0%, 0%) }
以上都是表示同一种颜色(红色)。
获取颜色属性的形式在ie和ff并不同,ff统一返回RGB颜色模式的第三种形式,ie则按照设置时的形式返回。

先说说RGB颜色模式,前两种比较常用应该都明白他们的区别吧,它用的是16进制表示形式,而我们想要10进制的。
把一个16进制表示的字符转成10进制数字,一般用parseInt,在substr截取字符之后就可以用parseInt转换。
对于#ff0000这个形式可以这样转换:


return  Map([color.substr( 1 2 ), color.substr( 3 2 ), color.substr( 5 2 )],
    
function (x){  return  parseInt(x,  16 ); }
)


parseInt的第二个参数就是第一个参数的进制值。
对于#f00形式,跟上一个差不多,只是转换之前要先换成完整表示形式:


return  Map([color.substr( 1 1 ), color.substr( 2 1 ), color.substr( 3 1 )],
    
function (x){  return  parseInt(x  +  x,  16 ); }
)

 

后面两种可能用的就比较少了,一个用10进制的rgb颜色值表示,另一个用百分比来表示。
ff严格按照那样的格式来表示,而ie就“放松”很多,例如:
ie可以允许数字百分比混用,ff不可以;
ff必须有逗号分隔,ie可以只用空格分隔;
当然我们使用时最好是按照w3c的标准来设置了。
ps:那个DHTML 手册上写的 EM { color: rgb 1.0 0.0 0.0 } 根本不能用的,不要被误导了。
对这个形式,程序用正则取得数值,如果有%就根据百分比计算出对应数值:


return  Map(color.match( / /d+(/./d+)?/%? / g),
    
function (x){  return  parseInt(x.indexOf( " % " >   0   ?  parseFloat(x,  10 *   2.55  : x,  10 ); }
)

 

而关键词大家都很熟悉,要转化却很麻烦,因为没有一定规律只能一个一个对应:


var  mapping  =  { " red " : " #FF0000 " }; //
color  =  mapping[color.toLowerCase()];
if (color){
    
return  Map([color.substr( 1 2 ), color.substr( 3 2 ), color.substr( 5 2 )],
        
function (x){  return  parseInt(x,  16 ); }
    )
}

 

在Create创建颜色集合程序中获得开始颜色和结束颜色的数据后,再根据Step(多少步)就可以获得步长了:


startColor  =   this .GetColor( this .StartColor),
endColor 
=   this .GetColor( this .EndColor),
stepR 
=  (endColor[ 0 -  startColor[ 0 ])  /   this .Step,
stepG 
=  (endColor[ 1 -  startColor[ 1 ])  /   this .Step,
stepB 
=  (endColor[ 2 -  startColor[ 2 ])  /   this .Step;


再根据步长生成集合:


for ( var  i  =   0 , n  =   this .Step, r  =  startColor[ 0 ], g  =  startColor[ 1 ], b  =  startColor[ 2 ]; i  <  n; i ++ ){
    colors.push([r, g, b]); r 
+=  stepR; g  +=  stepG; b  +=  stepB;
}
colors.push(endColor);

 

正确的颜色值是在0到255之间的,而且是不带小数的,所以最好修正一下:


return  Map(colors,  function (x){  return  Map(x,  function (x){
    
return  Math.min(Math.max( 0 , Math.floor(x)),  255 );
});});

 


【ColorTrans颜色渐变】

有了颜色梯度集合,只需要设个定时器把集合的值依次显示就是一个渐变效果了。
这个渐变一般是分两个步骤,分别是(FadeIn)和渐出(FadeOut)。
原理就是通过改变_index集合索引,渐入时逐渐变大,渐出时逐渐变小:


   // 颜色渐入
  FadeIn:  function () {
    
this .Stop();  this ._index ++ this .SetColor();
    
if ( this ._index  <   this ._colors.length  -   1 ){
        
this ._timer  =  setTimeout(Bind( this this .FadeIn),  this .Speed);
    }
  },
  
// 颜色渐出
  FadeOut:  function () {
    
this .Stop();  this ._index -- this .SetColor();
    
if ( this ._index  >   0 ){
        
this ._timer  =  setTimeout(Bind( this this .FadeOut),  this .Speed);
    }
  },


在SetColor设置样式程序中,通过CssColor来设置要修改的样式属性,例如字体颜色是"color",背景色是"backgroundColor":

var  color  =   this ._colors[Math.min(Math.max( 0 this ._index),  this ._colors.length  -   1 )];
this ._obj.style[ this .CssColor]  =   " rgb( "   +  color[ 0 +   " , "   +  color[ 1 +   " , "   +  color[ 2 +   " ) " ;

 

由于颜色集合是根据开始颜色、结束颜色和步数生成的,所以如果要修改这些属性必须重新生成过集合。
Reset程序就是用来修改这些属性并重新生成集合的,集合重新生成后索引也要设回0:


// 修改颜色后必须重新获取颜色集合
color  =  Extend({ StartColor:  this ._startColor, EndColor:  this ._endColor, Step:  this ._step }, color  ||  {});
// 设置属性
this ._grads.StartColor  =   this ._startColor  =  color.StartColor;
this ._grads.EndColor  =   this ._endColor  =  color.EndColor;
this ._grads.Step  =   this ._step  =  color.Step;
// 获取颜色集合
this ._colors  =   this ._grads.Create();
this ._index  =   0 ;

 


使用技巧

在颜色渐变菜单中,并没有使用链接标签a,原因是a的伪类的颜色并不能直接用js来修改(除非改class)。
暂时没想到很好的方法,只好用onclick跳转代替了。

在测试过程中还发现一个关于数组的问题,在ie和ff运行alert([,,].length)会分别显示3和2。
最后一个元素不写的话ff就会忽略这个元素,只要写的话就不会忽略即使是undefined和null,看了下文档也找到原因。
所以这个情况还是插一个东西进去,觉得不好看就new Array好了。

测试中还发现chrome(1.0.154.48)的map一个问题,map是js1.6的Array的方法,ff和chrome都支持(具体看这里 )。
在ff中[,,1].map(function(){return 0})返回的是[0,0,0],但chrome却返回[,,0]。
即在chrome中如果元素是空(不包括null和undefined)的话就一律返回空,用new Array来创建也一样。
感觉这样不太合理,应该以后会改进吧。

 

使用说明

ColorGrads只有3个属性设置:
StartColor: "#fff",//开始颜色
EndColor: "#000",//结束颜色
Step:  20//渐变级数
设置好属性后用Create生成集合就行了。

ColorTrans只要一个参数,要实现渐变的对象,可设置以下属性:
StartColor: "",//开始颜色
EndColor: "#000",//结束颜色
Step:  20,//渐变级数
Speed:  20,//渐变速度
CssColor: "color"//设置属性(Scripting属性)
如果不设置StartColor会自动使用CurrentStyle获取的样式值。
其中StartColor、EndColor和Step在实例化后要重新设置的话需要用Reset来设置。

具体使用请参考实例。

 

程序代码

ColorGrads部分:


var  ColorGrads  =   function (options){
    
this .SetOptions(options);
    
this .StartColor  =   this .options.StartColor;
    
this .EndColor  =   this .options.EndColor;
    
this .Step  =  Math.abs( this .options.Step);
};
ColorGrads.prototype 
=  {
  
// 设置默认属性
  SetOptions:  function (options) {
    
this .options  =  { // 默认值
        StartColor:     " #fff " , // 开始颜色
        EndColor:     " #000 " , // 结束颜色
        Step:         20 // 渐变级数
    };
    Extend(
this .options, options  ||  {});
  },
  
// 获取渐变颜色集合
  Create:  function () {
    
var  colors  =  [],
        startColor 
=   this .GetColor( this .StartColor),
        endColor 
=   this .GetColor( this .EndColor),
        stepR 
=  (endColor[ 0 -  startColor[ 0 ])  /   this .Step,
        stepG 
=  (endColor[ 1 -  startColor[ 1 ])  /   this .Step,
        stepB 
=  (endColor[ 2 -  startColor[ 2 ])  /   this .Step;
    
// 生成颜色集合
     for ( var  i  =   0 , n  =   this .Step, r  =  startColor[ 0 ], g  =  startColor[ 1 ], b  =  startColor[ 2 ]; i  <  n; i ++ ){
        colors.push([r, g, b]); r 
+=  stepR; g  +=  stepG; b  +=  stepB;
    }
    colors.push(endColor);
    
// 修正颜色值
     return  Map(colors,  function (x){  return  Map(x,  function (x){
        
return  Math.min(Math.max( 0 , Math.floor(x)),  255 );
    });});
  },
  
// 获取颜色数据
  GetColor:  function (color) {
    
if ( / ^#[0-9a-f]{6}$ / i.test(color))
    {
// #rrggbb
         return  Map([color.substr( 1 2 ), color.substr( 3 2 ), color.substr( 5 2 )],
            
function (x){  return  parseInt(x,  16 ); }
        )
    }
    
else   if ( / ^#[0-9a-f]{3}$ / i.test(color))
    {
// #rgb
         return  Map([color.substr( 1 1 ), color.substr( 2 1 ), color.substr( 3 1 )],
            
function (x){  return  parseInt(x  +  x,  16 ); }
        )
    }
    
else   if ( / ^rgb(.*)$ / i.test(color))
    {
// rgb(n,n,n) or rgb(n%,n%,n%)
         return  Map(color.match( / /d+(/./d+)?/%? / g),
            
function (x){  return  parseInt(x.indexOf( " % " >   0   ?  parseFloat(x,  10 *   2.55  : x,  10 ); }
        )
    }
    
else
    {
// color
         var  mapping  =  { " red " : " #FF0000 " }; //
        color  =  mapping[color.toLowerCase()];
        
if (color){
            
return  Map([color.substr( 1 2 ), color.substr( 3 2 ), color.substr( 5 2 )],
                
function (x){  return  parseInt(x,  16 ); }
            )
        }
    }
  }
};

 

 ColorTrans部分:


var  ColorTrans  =   function (obj, options){
    
    
this ._obj  =  $(obj);
    
this ._timer  =   null ; // 定时器
     this ._index  =   0 ; // 索引
     this ._colors  =  []; // 颜色集合
     this ._grads  =   new  ColorGrads();
    
    
this .SetOptions(options);
    
    
this .Speed  =  Math.abs( this .options.Speed);
    
this .CssColor  =   this .options.CssColor;
    
    
this ._startColor  =   this .options.StartColor  ||  CurrentStyle( this ._obj)[ this .CssColor];
    
this ._endColor  =   this .options.EndColor;
    
this ._step  =  Math.abs( this .options.Step);
    
    
this .Reset();
    
this .SetColor();
};
ColorTrans.prototype 
=  {
  
// 设置默认属性
  SetOptions:  function (options) {
    
this .options  =  { // 默认值
        StartColor:     "" , // 开始颜色
        EndColor:     " #000 " , // 结束颜色
        Step:         20 , // 渐变级数
        Speed:         20 , // 渐变速度
        CssColor:     " color " // 设置属性(Scripting属性)
    };
    Extend(
this .options, options  ||  {});
  },
  
// 重设颜色集合
  Reset:  function (color) {
    
// 修改颜色后必须重新获取颜色集合
    color  =  Extend({ StartColor:  this ._startColor, EndColor:  this ._endColor, Step:  this ._step }, color  ||  {});
    
// 设置属性
     this ._grads.StartColor  =   this ._startColor  =  color.StartColor;
    
this ._grads.EndColor  =   this ._endColor  =  color.EndColor;
    
this ._grads.Step  =   this ._step  =  color.Step;
    
// 获取颜色集合
     this ._colors  =   this ._grads.Create();
    
this ._index  =   0 ;
  },
  
// 颜色渐入
  FadeIn:  function () {
    
this .Stop();  this ._index ++ this .SetColor();
    
if ( this ._index  <   this ._colors.length  -   1 ){
        
this ._timer  =  setTimeout(Bind( this this .FadeIn),  this .Speed);
    }
  },
  
// 颜色渐出
  FadeOut:  function () {
    
this .Stop();  this ._index -- this .SetColor();
    
if ( this ._index  >   0 ){
        
this ._timer  =  setTimeout(Bind( this this .FadeOut),  this .Speed);
    }
  },
  
// 颜色设置
  SetColor:  function () {
    
var  color  =   this ._colors[Math.min(Math.max( 0 this ._index),  this ._colors.length  -   1 )];
    
this ._obj.style[ this .CssColor]  =   " rgb( "   +  color[ 0 +   " , "   +  color[ 1 +   " , "   +  color[ 2 +   " ) " ;
  },
  
// 停止
  Stop:  function () {
    clearTimeout(
this ._timer);
  }
};

 

下载完整实例

转载请注明出处: http://www.cnblogs.com/cloudgamer/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值