javascript 线性渐变二

  作者:bea

先来IE的,这是最大的用户群,如果这部分开发不出来,基本可以说不用做了。IE虽然有Gradient滤镜,但对比其他浏览器的实现特弱,没有多重渐变(stop-color),不能实现角度渐变,而且还经常失效。我的思路是这样,假如有一个带文本的DIV,要实现多重线性渐变,我们首先得把它里面的文本取出来,然后里面放几个DIV,有几重就放几个,然后把它们渐变。如果是垂直渐变,这好办,什么也不用做,只需设置其滤镜与各个高就行了。如果水平,就让其浮动或绝对定位,放到适当的位置,设置其滤镜与
先来IE的,这是最大的用户群,如果这部分开发不出来,基本可以说不用做了。IE虽然有Gradient滤镜,但对比其他浏览器的实现特弱,没有多重渐变(stop-color),不能实现角度渐变,而且还经常失效。我的思路是这样,假如有一个带文本的DIV,要实现多重线性渐变,我们首先得把它里面的文本取出来,然后里面放几个DIV,有几重就放几个,然后把它们渐变。如果是垂直渐变,这好办,什么也不用做,只需设置其滤镜与各个高就行了。如果水平,就让其浮动或绝对定位,放到适当的位置,设置其滤镜与宽。但渐变滤镜竟然会在浮动后或定位后失效,这是在使用透明滤镜时闻所未闻的。没有办法,祭出上古神器table。但设置长与宽时,使用style来设置是不顶用的,一定要用DOM属性。渐变则由它的td元素负责。为了去除table元素与td元素之间,td元素与其内容之间的空白,我们还得用到cellPadding与cellSpacing。



<!doctype html>
<title>javascript线性渐变 by 司徒正美</title>
<meta charset="utf-8"/>
<meta name="keywords" content="javascript线性渐变 by 司徒正美" />
<meta name="description" content="javascript线性渐变 by 司徒正美" />
<style type="text/css">
#gradient{
width:800px;
height:200px;
border:1px solid red;
}
</style>
<script type="text/javascript">
//④使用IE滤镜实现渐变
function setFilter(el,start,end,type){
el.style.filter = "progid:DXImageTransform.Microsoft.Gradient(enabled='true',startColorstr="+start+",GradientType="+type+", endColorstr="+end+")";
}
//③每个渐变体的实现,是用table还是div
function createStop(parent,top,left,width,height,type){
if(type){
var table = document.createElement("table");
parent.appendChild(table);
var tr = table.insertRow(0),
td = tr.insertCell(0)
table.height = height+"px";
table.width = width+"px";
table.cellPadding = 0;
table.cellSpacing = 0;
table.style.cssText = "position:absolute;top:"+top+"px;left:"+left+"px"
td.innerHTML =" ";
return td;
}
var div = document.createElement("div");
parent.appendChild(div);
div.style.height = height+"px";
div.style.width = width+"px";
return div;
}
//②渐变的具体实现,确定要使用多少渐变体,每个渐变体的颜色(是渐变色还是纯色)与长宽坐标
var IEgradient = function(entity,stops,width,height,type){
var offset,color,beforeColor,stopWidth,stopHeight,left,top,stop;
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
offset = stops[i].split(",")[0];
color = stops[i].split(",")[1];
stopWidth = (offset/100 * width).toFixed(1);
stopHeight = (offset/100 * height).toFixed(1);
switch(i){
case 0 :
beforeColor = color;
left = stopWidth;
top = stopHeight;
if(offset != 0){
//插入一个纯色的table
stop = type? createStop(entity,0,0,stopWidth,height,type) :
createStop(entity,0,0,width,stopHeight,type);
stop.style.backgroundColor = color;
}
break;
case l-1:
//先插入一个渐变的table
var w2 = ((100-offset)/100 * width).toFixed(1),
h2 = ((100-offset)/100 * height).toFixed(1),
stop = type? createStop(entity,0,left,width - left -w2,height,type):
createStop(entity,0,0,width,height - top -h2,type);
setFilter(stop,beforeColor,color,type);
if(offset != 100){
//再插入一个纯色的table
var stop2 = type? createStop(entity,0,stopWidth,w2,height,type):
createStop(entity,0,0,width,h2,type);
stop2.style.backgroundColor = color;
}
break;
default :
//插入一个渐变的table
stop = type ? createStop(entity,0,left,stopWidth - left,height,type) :
createStop(entity,0,0,width,stopHeight-top,type);
setFilter(stop,beforeColor,color,type);
beforeColor = color;
left = stopWidth;
top = stopHeight;
break;
}
}
}
//①渐变的主体函数
var gradient = function(id){
var entity = document.getElementById(id),
options = arguments[1] || {},
width = options.width,
height = options.height,
type = options.type ,
stops = options["color-stop"];
entity.style.position = "relative";
var content = entity.innerHTML;
entity.innerHTML = "";
//向目标对象进行渐变。
IEgradient(entity,stops,width,height,type);
//把原来的内容重新加入的目标对象。
var contentDiv = document.createElement("div");
contentDiv.style.cssText = "position:absolute;top:0;left:0";
contentDiv.innerHTML = content;
entity.appendChild(contentDiv);
}
window.onload = function(){
gradient("gradient",{width:800,height:200,type:1,"color-stop":["0,red","16,orange","32,yellow","48,green","64,blue","80,indigo","100,violet"]})
}
</script>
<div id="gradient">javascript线性渐变 by 司徒正美 实现多重水平渐变效果</div>
<p">必须在IE中才能看到效果!</p>




[Ctrl+A 全选 注:
如需引入外部Js需刷新才能执行]

safari,chrome与opera打算都用SVG实现。为了减少函数的长度,特意搞了两个辅助函数。


代码如下:


var createSVG = function(tag){
return document.createElementNS("http://www.w3.org/2000/svg",tag);
};
var attr= function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
};
var COSgradient = function(entity,stops,width,height,type){
var svg = createSVG("svg");
attr(svg,{width:width+"px",height:height+"px"})
entity.appendChild(svg);
.
var defs = createSVG("defs");
svg.appendChild(defs);
var linearGradient = createSVG("linearGradient");
defs.appendChild(linearGradient);
attr(linearGradient,{id:"nasami",x1:"0%",y1:"0%"})
if(type){
attr(linearGradient,{x2:"100%",y2:"0%"})
}else{
attr(linearGradient,{x2:"0%",y2:"100%"})
}
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
var offset = stops[i].split(",")[0] + "%",
color = stops[i].split(",")[1],
stop = createSVG("stop");
attr(stop,{offset:offset,"stop-color":color});
linearGradient.appendChild(stop);
}
var rect = createSVG("rect");
svg.appendChild(rect);
attr(rect,{x:"0px",y:"0px",width:width+"px",height:height+"px",fill:"url(#nasami)"});
}


firefox则利用其私有属性:


代码如下:


var FFgradient= function(entity,stops,width,height,type){
var cssText = ";background: -moz-linear-gradient("
cssText += type? "top,bottom," :"left,right,";
.
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
var offset = stops[i].split(",")[0] + "%",
color = stops[i].split(",")[1];
cssText += "color-stop("+[offset,color]+"),"
}
cssText = cssText.replace(/,$/,"")+") no-repeat;";
entity.style.cssText = cssText+"width:"+width+"px;height:"+height+"px;"
}


不过今天研磨一下,发现firefox还是支持SVG的线性渐变的,因此纠正我原来的观点。上面的函数只是作用一种实现手段放在这里,它并没有整合到我最终的版本中(虽然它比SVG实现短很多。)这样一来,在老一点版本的firefox中我们也能实现线性渐变了。
下面这个运行框里的渐变效果可在所有主流浏览器中正常运作。



<!doctype html>
<title>javascript线性渐变 by 司徒正美</title>
<meta charset="utf-8"/>
<meta name="keywords" content="javascript线性渐变 by 司徒正美" />
<meta name="description" content="javascript线性渐变 by 司徒正美" />
<style type="text/css">
#gradient{
width:800px;
height:100px;
border:1px solid red;
}
</style>
<script type="text/javascript">
var attr= function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
};
//④使用IE滤镜实现渐变
function setFilter(el,start,end,type){
el.style.filter = "progid:DXImageTransform.Microsoft.Gradient(enabled='true',startColorstr="+start+",GradientType="+type+", endColorstr="+end+")";
}
//③每个渐变体的实现,是用table还是div
function createStop(parent,top,left,width,height,type){
if(type){
var table = document.createElement("table");
parent.appendChild(table);
var tr = table.insertRow(0),
td = tr.insertCell(0)
attr(table,{height:height+"px",width:width+"px",cellPadding:0,cellSpacing:0})
css(table,{position:"absolute",top:top+"px",left:left+"px"});
td.innerHTML =" ";
return td;
}
var div = document.createElement("div");
parent.appendChild(div);
css(div,{height:height+"px",width:width+"px"})
return div;
};
var createSVG = function(tag){
return document.createElementNS("http://www.w3.org/2000/svg",tag);
};
var css = function(node,bag){
var str = ";"
for(var i in bag){
if(bag.hasOwnProperty(i))
str += i+":"+bag[i]+";";
}
node.style.cssText = str;
}
var SVGgradient = function(entity,stops,width,height,type){
var svg = createSVG("svg");
attr(svg,{width:width+"px",height:height+"px"})
entity.appendChild(svg);
var defs = createSVG("defs");
svg.appendChild(defs);
var linearGradient = createSVG("linearGradient");
defs.appendChild(linearGradient);
attr(linearGradient,{id:"nasami",x1:"0%",y1:"0%"})
if(type){
attr(linearGradient,{x2:"100%",y2:"0%"})
}else{
attr(linearGradient,{x2:"0%",y2:"100%"})
}
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
var offset = stops[i].split(",")[0] + "%",
color = stops[i].split(",")[1],
stop = createSVG("stop");
attr(stop,{offset:offset,"stop-color":color});
linearGradient.appendChild(stop);
}
var rect = createSVG("rect");
svg.appendChild(rect);
attr(rect,{x:"0px",y:"0px",width:width+"px",height:height+"px",fill:"url(#nasami)"});
}
//②渐变的具体实现,确定要使用多少渐变体,每个渐变体的颜色(是渐变色还是纯色)与长宽坐标
var IEgradient = function(entity,stops,width,height,type){
var offset,color,beforeColor,stopWidth,stopHeight,left,top,stop;
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
offset = stops[i].split(",")[0];
color = stops[i].split(",")[1];
stopWidth = (offset/100 * width).toFixed(1);
stopHeight = (offset/100 * height).toFixed(1);
switch(i){
case 0 :
beforeColor = color;
left = stopWidth;
top = stopHeight;
if(offset != 0){
//插入一个纯色的table
stop = type? createStop(entity,0,0,stopWidth,height,type) :
createStop(entity,0,0,width,stopHeight,type);
css(stop,{background:color});
}
break;
case l-1:
//先插入一个渐变的table
var w2 = ((100-offset)/100 * width).toFixed(1),
h2 = ((100-offset)/100 * height).toFixed(1),
stop = type? createStop(entity,0,left,width - left -w2,height,type):
createStop(entity,0,0,width,height - top -h2,type);
setFilter(stop,beforeColor,color,type);
if(offset != 100){
//再插入一个纯色的table
var stop2 = type? createStop(entity,0,stopWidth,w2,height,type):
createStop(entity,0,0,width,h2,type);
css(stop2,{background:color});
}
break;
default :
//插入一个渐变的table
stop = type ? createStop(entity,0,left,stopWidth - left,height,type) :
createStop(entity,0,0,width,stopHeight-top,type);
setFilter(stop,beforeColor,color,type);
beforeColor = color;
left = stopWidth;
top = stopHeight;
break;
}
}
}
//①渐变的主体函数
var gradient = function(id){
var entity = document.getElementById(id),
options = arguments[1] || {},
width = options.width,
height = options.height,
type = options.type ,
stops = options["color-stop"];
css(entity,{position:"relative"});
var content = entity.innerHTML;
entity.innerHTML = "";
!+"v1"? IEgradient(entity,stops,width,height,type):
SVGgradient(entity,stops,width,height,type)
var contentDiv = document.createElement("div");
css(contentDiv,{position:"absolute",top:0,left:0})
contentDiv.innerHTML = content;
entity.appendChild(contentDiv);
}
window.onload = function(){
gradient("gradient",{width:800,height:100,type:1,"color-stop":["0,red","16,orange","32,yellow","48,green","64,blue","80,indigo","100,violet"]})
}
</script>
<div id="gradient">javascript线性渐变 by 司徒正美 实现多重水平渐变效果</div>
https://developer.mozilla.org/en/SVG/Tutorial/Fill_Stroke_and_Gradients




[Ctrl+A 全选 注:
如需引入外部Js需刷新才能执行]

再把它做成类。扼要说明一下:它的第一个参数为IE,第二个为哈希。哈希中的各参数都为必选的,width,height的单位为px;type为0或者1,0代表垂直,1为水平;color-stop代表渐变体,由一个字符串数组构成,每个字符串都是由数字加逗号加颜色值组成,数字表代偏移量,单位为%,颜色值可以是red,green等名词,也可以是六位或三位的哈希值。渐变体至少要有一个。


代码如下:


new Gradient("gradient",{width:800,height:100,type:0,"color-stop":["0,red",
3."16,orange","32,yellow","48,green","64,blue","80,indigo","100,violet"]})





<!doctype html>
<title>javascript线性渐变 by 司徒正美</title>
<meta charset="utf-8"/>
<meta name="keywords" content="javascript线性渐变 by 司徒正美" />
<meta name="description" content="javascript线性渐变 by 司徒正美" />
<style type="text/css">
.gradient{
width:800px;
height:100px;
}
</style>
<script type="text/javascript">
var Gradient = function(id){
var entity = document.getElementById(id),
options = arguments[1] || {},
width = options.width,
height = options.height,
type = options.type ,
stops = options["color-stop"];
this.init(entity,stops,width,height,type);
}
Gradient.prototype ={
constructor: Gradient,
init: function(entity,stops,width,height,type) {
this.css(entity,{position:"relative"});
var content = entity.innerHTML;
entity.innerHTML = "";
!+"v1"? this.IEgradient(entity,stops,width,height,type):
this.SVGgradient(entity,stops,width,height,type)
var contentDiv = document.createElement("div");
this.css(contentDiv,{position:"absolute",top:0,left:0})
contentDiv.innerHTML = content;
entity.appendChild(contentDiv);
},
css: function(node,bag){
var str = ";"
for(var i in bag){
if(bag.hasOwnProperty(i))
str += i+":"+bag[i]+";";
}
node.style.cssText = str;
},
attr: function(node,bag){
for(var i in bag){
if(bag.hasOwnProperty(i))
node.setAttribute(i,bag[i])
}
},
createSVG:function(tag){
return document.createElementNS("http://www.w3.org/2000/svg",tag);
},
setFilter:function(el,start,end,type){
el.style.filter = "progid:DXImageTransform.Microsoft.Gradient(enabled='true',startColorstr="+
start+",GradientType="+type+", endColorstr="+end+")";
},
createStop:function(parent,top,left,width,height,type){
if(type){
var table = document.createElement("table");
parent.appendChild(table);
var tr = table.insertRow(0),
td = tr.insertCell(0)
this.attr(table,{height:height+"px",width:width+"px",cellPadding:0,cellSpacing:0})
this.css(table,{position:"absolute",top:top+"px",left:left+"px"});
td.innerHTML =" ";
return td;
}
var div = document.createElement("div");
parent.appendChild(div);
this.css(div,{height:height+"px",width:width+"px"})
return div;
},
IEgradient:function(entity,stops,width,height,type){
var offset,color,beforeColor,stopWidth,stopHeight,left,top,stop;
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
offset = stops[i].split(",")[0];
color = this.hex(stops[i].split(",")[1]);
stopWidth = (offset/100 * width).toFixed(1);
stopHeight = (offset/100 * height).toFixed(1);
switch(i){
case 0 :
beforeColor = color;
left = stopWidth;
top = stopHeight;
if(offset != 0){
//插入一个纯色的table
stop = type? this.createStop(entity,0,0,stopWidth,height,type) :
this.createStop(entity,0,0,width,stopHeight,type);
this.css(stop,{background:color});
}
break;
case l-1:
//先插入一个渐变的table
var w2 = ((100-offset)/100 * width).toFixed(1),
h2 = ((100-offset)/100 * height).toFixed(1),
stop = type? this.createStop(entity,0,left,width - left -w2,height,type):
this.createStop(entity,0,0,width,height - top -h2,type);
this.setFilter(stop,beforeColor,color,type);
if(offset != 100){
//再插入一个纯色的table
var stop2 = type? this.createStop(entity,0,stopWidth,w2,height,type):
this.createStop(entity,0,0,width,h2,type);
this.css(stop2,{background:color});
}
break;
default :
//插入一个渐变的table
stop = type ? this.createStop(entity,0,left,stopWidth - left,height,type) :
this.createStop(entity,0,0,width,stopHeight-top,type);
this.setFilter(stop,beforeColor,color,type);
beforeColor = color;
left = stopWidth;
top = stopHeight;
break;
}
}
},
SVGgradient:function(entity,stops,width,height,type){
var svg = this.createSVG("svg"),
id = "id" + (new Date().getTime()* Math.random()).toFixed(0);
this.attr(svg,{width:width+"px",height:height+"px"})
entity.appendChild(svg);
var defs = this.createSVG("defs");
svg.appendChild(defs);
var linearGradient = this.createSVG("linearGradient");
defs.appendChild(linearGradient);
this.attr(linearGradient,{id:id,x1:"0%",y1:"0%"})
if(type){
this.attr(linearGradient,{x2:"100%",y2:"0%"})
}else{
this.attr(linearGradient,{x2:"0%",y2:"100%"})
}
for(var i=0,j=0,l=stops.length;i<l;i++,j++){
var offset = stops[i].split(",")[0] + "%",
color = this.hex(stops[i].split(",")[1]),
stop = this.createSVG("stop");
this.attr(stop,{offset:offset,"stop-color":color});
linearGradient.appendChild(stop);
}
var rect = this.createSVG("rect");
svg.appendChild(rect);
this.attr(rect,{x:"0px",y:"0px",width:width+"px",height:height+"px",
fill:"url(#"+linearGradient.getAttribute("id")+")"});
},
hex:function(value){
if(/^#/.test(value)){
value = value.replace('#', '');
return "#" + (value.length == 3 ? value.replace(/^(w)(w)(w)$/, '$1$1$2$2$3$3') : value);
}
return value;
}
}
window.onload = function(){
new Gradient("text1",{width:800,height:100,type:1,"color-stop":["0,red","16,orange","32,yellow","48,green","64,blue","80,indigo","100,violet"]})
new Gradient("text2",{width:800,height:100,type:0,"color-stop":["0,red","16,orange","32,yellow","48,green","64,blue","80,indigo","100,violet"]})
}
</script>
<div id="text1" class="gradient">javascript线性渐变 by 司徒正美 实现多重水平渐变效果</div>


<div id="text2" class="gradient">javascript线性渐变 by 司徒正美 实现多重垂直渐变效果</div>




[Ctrl+A 全选 注:
如需引入外部Js需刷新才能执行]



有用  |  无用

猜你喜欢