您的位置:首页 > Web前端 > JavaScript

JavaScript 渐变效果

2012-01-16 04:41 246 查看
======================================================

注:本文源代码点此下载

======================================================

javascript 渐变效果
程序集合了宽度、高度、透明度、top、left的渐变,可以自定义渐变项目和各个项目的初始值结束值,还能以任意点(定点)为中心渐变。
使用该程序能实现很多常见的动画特效,包括大小变换、位置变换、渐显渐隐等等。
效果:
程序说明:
渐变效果的原理就是利用定时器不断设置值,如果要减速效果就设置一个步长(详细看javascript 弹簧效果) 。
这里只是把能渐变的属性(透明度、宽、高、left、top)整合在一起,使用相同的渐变级数(step)使渐变同步,形成多个属性同时渐变的效果。
下面说说有用的地方:
【最终样式】
javascript 图片切割效果的边宽获取中也说到了最终样式,在使用offset获取的数据设置宽度高度的时候,必须先减去最终样式中的边框宽度。
在这里我使用了muxrwc的在ff下实现currentstyle方法,这样在ff和ie都可以从currentstyle获取最终样式了:




code
if(!isie){
htmlelement.prototype.__definegetter__("currentstyle", function () {
return this.ownerdocument.defaultview.getcomputedstyle(this, null);
});
}
使用这个获取边框宽度:
this._xborder = function(){ return (parseint(obj.currentstyle.borderleftwidth) + parseint(obj.currentstyle.borderrightwidth)); }
this._yborder = function(){ return (parseint(obj.currentstyle.bordertopwidth) + parseint(obj.currentstyle.borderbottomwidth)); }
【宽度或高度优先】
宽度或高度优先其实就是先执行其中一个渐变,在完成后再执行另一个渐变。
渐变程序中在执行完一次渐变之后会返回一个bool值表示是否渐变完成,利用这个可以这样:
this.setwidth() && this.setheight();
由于&&的特性,当this.setwidth()返回true时才会去执行this.setheight(),这也是不错的技巧。
同时为了同步渐变,另外的渐变使用了两倍的步长:




code
this.step = 2*this.step;
this.setopacity(); this.settop(); this.setleft();
this.step = this.step/2;
这样就能做出宽度或高度优先的效果了。
【定点渐变】
先说说原理,例如以宽度中点为参照点,可以想象如果宽度减少n,那只要left相对增加n*0.5(即n/2),
那么就可以做出以中点为中心变换的效果(当然要先把变换对象设为相对或绝对定位)。
那这个“0.5”怎么来的呢?有点数理知识应该知道就是渐变对象左边到变换点跟渐变对象总宽度的比
程序里用width.pos保存这个值,在变换前先计算好变换点的位置:
this._x = this._obj.offsetleft + this._obj.offsetwidth * this.width.pos;
每次变换都根据这个位置和宽度来重新设置left:
this._obj.style.left = this._x - this._obj.offsetwidth * this.width.pos + "px";
可能有人会说直接在原有left基础上加上变换宽度*width.pos不是一样吗?
但问题是经过多次的变换计算(到达目标值前会有多次计算)之后得到的值已经不准确了。
因为在变换计算过程中很多小数会被忽略,随着计算次数增多结果的出入也越大,
所以先定好变换位置参照值(_x),这样不论经过多少次计算变换位置都不会走位了。
同理只要设置不同的width.pos(包括负数和大于1的数)和height.pos就可以以任意点为中心渐变了。
还有就是程序的设计也花了不少心思,为了提高整合度,做了一个fadestruct的结构,其中run、start、end、target属性分别是是否渐变、开始值、结束值、目标值。
用了两次的object.extend来设置默认值,详细可以看程序。
使用说明:
必要的参数只有一个,就是渐变对象,不过只有渐变对象是没有效果的,必须设置其他属性:
opacity:透明渐变参数
height:高度渐变参数
width:宽度渐变参数
top:top渐变参数
left:left渐变参数
step:10,//变化率
time:10,//变化间隔
mode:"both",//渐变顺序
show:false,//是否默认打开状态
onfinish:function(){}//完成时执行
其中opacity、height、width、top、left比较特别,是fadestruct结构
例子里实例化这个对象:




code
var f = new fade("idfade", { show: true,
opacity: { run: true },
height: { run: true },
width: { run: true, pos: .5 },
top: { run: true, end: 70 }
});
设置run为true就表示开启这个变换,start和end是开始和结束值,pos是height和width特有的变换位置属性。
更详细的应用可以看实例。
程序代码:




code
var isie = (document.all) ? true : false;
var $ = function (id) {
return "string" == typeof id ? document.getelementbyid(id) : id;
};
if(!isie){
htmlelement.prototype.__definegetter__("currentstyle", function () {
return this.ownerdocument.defaultview.getcomputedstyle(this, null);
});
}
var class = {
create: function() {
return function() {
this.initialize.apply(this, arguments);
}
}
}
object.extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
return destination;
}
var fadestruct = function(options){
this.run = false;//是否渐变
this.start = 0;//开始值
this.end = 0;//结束值
this.target = 0;//目标值
object.extend(this, options || {});
}
var fade = class.create();
fade.prototype = {
initialize: function(obj, options) {
var obj = $(obj);
obj.style.overflow = "hidden";
this._obj = obj;
this._timer = null;//定时器
this._finish = true;//是否执行完成
this._fun = function(){};//渐变程序
this._x = this._y = 0;//变换点位置
//设置获取透明度程序
this._setopacity = isie ? function(opacity){ obj.style.filter = "alpha(opacity:" + opacity + ")"; } : function(opacity){ obj.style.opacity = opacity / 100; };
this._getopacity = isie ? function(){ return parseint(obj.filters["alpha"].opacity); } : function(opacity){ return 100 * parsefloat(obj.currentstyle.opacity); };
//获取边框宽度程序
this._xborder = function(){ return (parseint(obj.currentstyle.borderleftwidth) + parseint(obj.currentstyle.borderrightwidth)); }
this._yborder = function(){ return (parseint(obj.currentstyle.bordertopwidth) + parseint(obj.currentstyle.borderbottomwidth)); }
this.setoptions(options);
this.mode = this.options.mode;
this.time = math.abs(this.options.time);
this.onfinish = this.options.onfinish;
//先设置特殊默认值
this.opacity = new fadestruct({ end: 100 });
this.top = new fadestruct({ start: this._obj.offsettop, end: this._obj.offsettop });
this.left = new fadestruct({ start: this._obj.offsetleft, end: this._obj.offsetleft });
this.height = new fadestruct({ end: this._obj.offsetheight - this._yborder() });
this.width = new fadestruct({ end: this._obj.offsetwidth - this._xborder() });
//再设置用户默认值
object.extend(this.opacity, this.options.opacity);
object.extend(this.top, this.options.top);
object.extend(this.left, this.options.left);
object.extend(this.height, this.options.height);
object.extend(this.width, this.options.width);
//变换位置参数
this.height.pos = number(this.options.height.pos);
this.width.pos = number(this.options.width.pos);
//设置成默认状态
this.show = !this.options.show;
this.step = 1;
this.start();
//重新设置step
this.step = math.abs(this.options.step);
},
//设置默认属性
setoptions: function(options) {
this.options = {//默认值
opacity:{},//透明渐变参数
height:{},//高度渐变参数
width:{},//宽度渐变参数
top:{},//top渐变参数
left:{},//left渐变参数
step:10,//变化率
time:10,//变化间隔
mode:"both",//渐变顺序
show:false,//是否默认打开状态
onfinish:function(){}//完成时执行
};
object.extend(this.options, options || {});
},
//触发
start: function() {
cleartimeout(this._timer);
//取反表示要设置的状态
this.show = !this.show;
//为避免透明度为null值,需要先设置一次透明度
if(this.opacity.run){ this._setopacity(this.show ? this.opacity.start : this.opacity.end); }
//根据状态设置目标值
if(this.show){
this.opacity.target = this.opacity.end;
this.top.target = this.top.end;
this.left.target = this.left.end;
this.height.target = this.height.end;
this.width.target = this.width.end;
} else{
this.opacity.target = this.opacity.start;
this.top.target = this.top.start;
this.left.target = this.left.start;
this.height.target = this.height.start;
this.width.target = this.width.start;
}
//设置渐变程序
switch (this.mode.tolowercase()) {
case "width" :
this._fun = function(){
this.setwidth() && this.setheight();
//由于分了两步,下面的步长变成两倍
this.step = 2*this.step;
this.setopacity(); this.settop(); this.setleft();
this.step = this.step/2;
}
break;
case "height" :
this._fun = function(){
this.setheight() && this.setwidth();
//由于分了两步,下面的步长变成两倍
this.step = 2*this.step;
this.setopacity(); this.settop(); this.setleft();
this.step = this.step/2;
}
break;
case "both" :
default :
this._fun = function(){ this.setheight(); this.setwidth(); this.setopacity(); this.settop(); this.setleft();}
}
//获取变换点位置
//由于设置变换点后与top和left变换有冲突只能执行其一
if(this.height.pos){ this._y = this._obj.offsettop + this._obj.offsetheight * this.height.pos; this.top.run = false; }
if(this.width.pos){ this._x = this._obj.offsetleft + this._obj.offsetwidth * this.width.pos; this.left.run = false; }
this.run();
},
//执行
run: function() {
cleartimeout(this._timer);
this._finish = true;
//执行渐变
this._fun();
//未完成继续执行
if (this._finish) { this.onfinish(); }
else { var othis = this; this._timer = settimeout(function(){ othis.run(); }, this.time); }
},
//设置高度渐变
setheight: function() {
var iget = this.get(this.height, this._obj.offsetheight - this._yborder());
if(isnan(iget)) return true;
this._obj.style.height = iget + "px";
//如果有变换点设置
if(this.height.pos){ this._obj.style.top = this._y - this._obj.offsetheight * this.height.pos + "px"; }
return false;
},
//设置宽度渐变
setwidth: function() {
var iget = this.get(this.width, this._obj.offsetwidth - this._xborder());
if(isnan(iget)) return true;
this._obj.style.width = iget + "px";
if(this.width.pos){ this._obj.style.left = this._x - this._obj.offsetwidth * this.width.pos + "px"; }
return false;
},
//设置top渐变
settop: function() {
var iget = this.get(this.top, this._obj.offsettop);
if(isnan(iget)) return true;
this._obj.style.top = iget + "px";
return false;
},
//设置left渐变
setleft: function() {
var iget = this.get(this.left, this._obj.offsetleft);
if(isnan(iget)) return true;
this._obj.style.left = iget + "px";
return false;
},
//设置透明渐变
setopacity: function() {
var iget = this.get(this.opacity, this._getopacity());
if(isnan(iget)) return true;
this._setopacity(iget);
return false;
},
//获取设置值
get: function(o, now){
if(o.run){
var istep = (o.target - now) / this.step;
if(istep){
this._finish = false;
if(math.abs(istep)1){ istep = istep > 0 ? 1 : -1; }
return now + istep;
}
}
}
};
下载完整测试代码
转载请注明出处:http://www.cnblogs.com/cloudgamer/
如有任何建议或疑问,欢迎留言讨论。
如果觉得文章不错的话,欢迎点一下右下角的推荐。
程序中包含的js工具库cjl.0.1.min.js,原文在这里
标签:
javascript, 渐变
绿色通道:好文要顶关注我收藏该文与我联系



posted @ 2008-08-27 00:17
cloudgamer 阅读(25645)
评论(59)编辑
收藏
发表评论
1990822
回复 引用
#1楼 2008-08-27 00:19 astarnologin[未注册用户]
不错
回复 引用 查看
#2楼 2008-08-27 00:19 悟〈--觉

真帅,有源代码不?
回复 引用 查看
#3楼[楼主] 2008-08-27 01:04 cloudgamer

@astarnologin
谢谢
@悟〈--觉
贴出来了
不过还没完成的
回复 引用 查看
#4楼 2008-08-27 01:04 崇山峻岭

楼主...强...小弟向你看齐.....可以将整个源源码参考吗...呵呵sunjun2008@163.com
回复 引用 查看
#5楼[楼主] 2008-08-27 01:06 cloudgamer

@崇山峻岭
等我完成后会放完全的测试代码下载的
回复 引用
#6楼 2008-08-27 01:24 astarnologin[未注册用户]
呵呵,都不睡呀。注意身体哦
回复 引用 查看
#7楼 2008-08-27 07:52 一杰

很强大,支持下。
回复 引用 查看
#8楼 2008-08-27 08:32 小情

很强大,支持下。
回复 引用 查看
#9楼 2008-08-27 08:51 exile

mm好漂亮,@^@
回复 引用 查看
#10楼 2008-08-27 08:55 侯垒

不错.
回复 引用 查看
#11楼[楼主] 2008-08-27 09:01 cloudgamer

@astarnologin
谢谢关心
@jannock
@一杰
@小情
@exile
@侯垒
谢谢支持
回复 引用
#12楼 2008-08-27 09:11 爽肤水[未注册用户]
效果不错,妞也不错
回复 引用 查看
#13楼 2008-08-27 09:13 对月而歌

支持 支持
回复 引用 查看
#14楼 2008-08-27 09:14 such cloud

一大早看到 支持一下!
回复 引用 查看
#15楼 2008-08-27 09:20 michaellu

看了那个妞不错啊,哈哈
回复 引用 查看
#16楼 2008-08-27 09:22 michaellu

大清早,不顶不行。
回复 引用 查看
#17楼 2008-08-27 09:28 爱上北溟鸟

再顶一个
回复 引用 查看
#18楼 2008-08-27 09:28 海皮球

酷呆了!不错!
回复 引用
#19楼 2008-08-27 09:38 graystar[未注册用户]
代码写得好不好不要紧,关键是妞正不正点.
回复 引用 查看
#20楼 2008-08-27 09:54 阿一(杨正祎)

效果果然不错。
回复 引用 查看
#21楼 2008-08-27 09:54 有容乃大

值得欣赏,赞一下。
回复 引用 查看
#22楼 2008-08-27 10:06 ryan gene

var fade = class.create();
base on prototype framework?
回复 引用 查看
#23楼[楼主] 2008-08-27 10:13 cloudgamer

@爽肤水
@对月而歌
@such cloud
@michaellu
@michaellu
@爱上北溟鸟
@海皮球
@graystar
@阿一(杨正祎)
@有容乃大
谢谢支持
@ryan gene
是使用了prototype 的类结构但没有真的使用框架
回复 引用 查看
#24楼 2008-08-27 10:42 cat chen

这些简单的效果直接去用prototype+scriptaculous就好了,用不着自己写。复杂的效果,可以基于scriptaculous来写。
回复 引用 查看
#25楼[楼主] 2008-08-27 10:49 cloudgamer

@cat chen
这是个人兴趣用于学习
用框架感觉意义就不大了
回复 引用 查看
#26楼 2008-08-27 12:25 烟仔

支持 支持
回复 引用
#27楼 2008-08-27 13:16 zbinxp[未注册用户]
楼主的失误之处在于那张图片,让代码都黯然失色了
不过我美女看太多了,没有感觉了。还是学习一下代码先
回复 引用 查看
#28楼[楼主] 2008-08-27 14:33 cloudgamer

@烟仔
@zbinxp
谢谢
回复 引用 查看
#29楼 2008-08-27 16:45 love&tiger

lz很刻苦呀,那么晚了还在忙
回复 引用 查看
#30楼[楼主] 2008-08-27 17:22 cloudgamer

@love&tiger
谢谢关心
回复 引用 查看
#31楼 2008-08-27 21:22 阿滨

我要美女不要代码啊!!
回复 引用 查看
#32楼[楼主] 2008-09-02 21:45 cloudgamer

@阿滨
美女图片地址 http://images.cnblogs.com/cnblogs_com/cloudgamer/143727/r_mm14.jpg 回复 引用 查看
#33楼 2008-10-03 10:33 漂零

太强大了
回复 引用 查看
#34楼[楼主] 2008-10-03 15:20 cloudgamer

@漂零
谢谢支持
回复 引用 查看
#35楼 2008-10-13 18:45 daml

学习中。。
回复 引用 查看
#36楼[楼主] 2008-10-14 08:40 cloudgamer

@daml
共同学习
回复 引用
#37楼 2008-10-29 19:08 剑无名[未注册用户]
大哥你真nb
回复 引用 查看
#38楼[楼主] 2008-10-29 21:14 cloudgamer

@剑无名
谢谢支持
回复 引用
#39楼 2008-10-30 10:02 剑无名[未注册用户]
我想问下,idcontainer的onclick事件函数中,在f.start()之前的代码是处理什么的?还有我改变了fade的width.pos值,但是看不到有什么效果,能不能帮忙解答一下,谢谢!
回复 引用 查看
#40楼[楼主] 2008-10-30 20:17 cloudgamer

@剑无名
如果f.show即打开状态时设置f.width.pos,f.height.pos
即变换点位置
目的是使渐变关闭点设置到点击位置
使用这个两个属性必须是相对定位或绝对定位
还是不明白的话可以发代码给我看看
回复 引用 查看
#41楼 2008-11-13 10:11 言学

好帅气啊。
回复 引用
#42楼 2008-12-04 09:19 gyct[未注册用户]
博主你太nb了~
每篇日志对我都有很大的价值哦~
虽然我是后台程序员,但是也得到很多帮助,谢谢~
回复 引用
#43楼 2009-02-10 09:01 jaychaoqun[未注册用户]
mm身材不错
回复 引用
#44楼 2009-05-17 12:48 wrw[未注册用户]
拜托代码............................
回复 引用 查看
#45楼[楼主] 2009-05-17 13:02 cloudgamer

@wrw
上面已经有测试代码下载
@jaychaoqun
@gyct
@言学
谢谢支持
回复 引用
#46楼 2009-05-19 09:21 很强的内容[未注册用户]
为什么全是美女
哎,什么什么欲动
回复 引用
#47楼 2009-05-21 00:18 wtcsy[未注册用户]
拜读了很久,顺便模仿了一下
基本上是按你的思路来的
可是出问题了,可否指教一下(部分步骤不一样!~)..............
回复 引用 查看
#48楼[楼主] 2009-05-21 08:25 cloudgamer

@很强的内容
呵呵
@wtcsy
其实这东西最好还是参考jq的
不知你的是什么问题
回复 引用
#49楼 2009-05-21 11:23 wtcsy[未注册用户]
发送到了你的邮箱.期待解答!~
回复 引用 查看
#50楼 2009-06-02 02:12 selfocus

支持一下,期待更多精品
回复 引用 查看
#51楼 2009-08-09 01:36 江苏-茄子

哪几个例子是比较基础的啊?前辈能不能告知一下qq号码!以后讨教一下阿
回复 引用 查看
#52楼[楼主] 2009-08-09 18:29 cloudgamer

@江苏-茄子
也就二十篇左右,你可以选适合的看
有什么问题可以留言或email
@selfocus
谢谢支持
回复 引用
#53楼 2009-08-11 03:35 磊子的[未注册用户]
空间绝后 jascript大师一级!
回复 引用 查看
#54楼 2009-08-21 18:03 江苏-茄子

@cloudgamer
您主要用的什么知识点啊!我今天看了一下prototype!是不是主要用的这个啊!
用没用什么jquery啊
回复 引用 查看
#55楼[楼主] 2009-08-21 20:07 cloudgamer

@磊子的
谢谢支持
@江苏-茄子
风格开始是参考prototype.js现在也有一些自己的风格
回复 引用
#56楼 2009-08-25 23:03 qqww1122[未注册用户]
看完之后觉得自己啥都不会
回复 引用 查看
#57楼[楼主] 2009-08-25 23:21 cloudgamer

@qqww1122
是说文章没有可取之处还是...?
回复 引用 查看
#58楼 2010-12-17 17:29 前 端

为什么每次下载源代码都下的是个login.aspx的文档呢???
回复 引用 查看
#59楼[楼主] 2010-12-18 08:53 cloudgamer

@前 端
右键另存为
刷新评论列表刷新页面返回页首
发表评论
昵称:
[登录]
[注册]
主页:
邮箱:(仅博主可见)
验证码:看不清。

换一个
评论内容:
记住我的昵称和主页
-->
登录注册
[使用ctrl+enter键快速提交评论]
0
1277131
tizx5rrme7q=
首页博问闪存新闻园子招聘知识库
最新it新闻:
·windows 7官方rss动态主题:《昆虫》
·捡到iphone 4s玩自拍 icloud同步酿悲剧
·铁道部购票网站存泄密危险 cdn服务商技术短板是主因
·利用 mimo magictouch 打造另类的平板电脑
·但愿大嘴巴的消息再次失准
»
更多新闻...
最新知识库文章:
·设计师的品牌意识
·如何成为“10倍效率”开发者
·快速排序(quicksort)的javascript实现
·wcf服务端运行时架构体系详解[续篇]
·wcf服务端运行时架构体系详解[下篇]
»
更多知识库文章...



china-pub 2011秋季教材巡展
china-pub 计算机绝版图书按需印刷服务

======================================================

在最后,我邀请大家参加新浪APP,就是新浪免费送大家的一个空间,支持PHP+MySql,免费二级域名,免费域名绑定
这个是我邀请的地址,您通过这个链接注册即为我的好友,并获赠云豆500个,价值5元哦!短网址是http://t.cn/SXOiLh我创建的小站每天访客已经达到2000+了,每天挂广告赚50+元哦,呵呵,饭钱不愁了,\(^o^)/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: