javascript 小型动画组件与实现代码


Posted in PHP onJune 02, 2010

做一个普通的动画效果,js是怎么完成的呢.看一下例子

setInterval(function(){ 
element.style.left =parseFloat(element.style.left) +(n) +'px'; 
},10);


[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

用window.setInterval 动画函数 ,每隔10毫秒 都会去执行一次动画 ;
和 set配套的是 clearInterval 函数,用来结束动画。
每隔setInterval 都会返回一个类似于线程id的值 ;
var interval =setInterval(function(){
element.style.left =parseFloat(element.style.left) +(n) +'px';
},10);
用 clearInterval (interval) 既可结束动画播放.
interval = setInterval(function(){
if(parseFloat(element.style.left)>500) clearInterval(interval)
element.style.left =parseFloat(element.style.left) +2 +'px';
},10);
超过500px的时候,动画就会停止, element将不在移动。

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

但是上面的动画是比较生硬的,然后我们有另外一种时间线动画。
看例子:
var element = document.getElementById('test1');
var start = +new Date,dur=1000,finish = start+dur;
interval = setInterval(function(){
var time = +new Date,
pos = time > finish ? 1 : (time-start)/dur;
element.style.left = (100*pos)+"px";
if(time>finish) {
clearInterval(interval);
}
},10);
start 为目标动画的开始时间 ( +new Date 其实就是 new Date().getTime() )
dur 为 动画执行一共所需要的时间
finish 是目标动画结束的时间
pos = time > finish ? 1 : (time-start)/dur; //可以把pos 想象成频率 ,一个时间比
(100*pos) ,100代表距离,,如果距离为500px 就设置为 500*pos;
time>finish : 如果超过时间,就停止动画!

[Ctrl+A 全选 注:引入外部Js需再刷新一下页面才能执行]

很好,到这里我们已经知道一个简单动画效果是怎么样写的了.
再来看一个小型的完整的动画组件是如何写的 :
(function($,name){ 
var parseEl = document.createElement('div') 
, 
props = ('backgroundColor borderBottomColor borderBottomWidth borderLeftColor borderLeftWidth '+ 
'borderRightColor borderRightWidth borderSpacing borderTopColor borderTopWidth bottom color fontSize '+ 
'fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop maxHeight '+ 
'maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft '+ 
'paddingRight paddingTop right textIndent top width wordSpacing zIndex').split(' ') 
, 
normalize =function (style){ 
var css, 
rules = {}, 
i = props.length, 
v; 
parseEl.innerHTML = '<div style="'+style+'"></div>'; 
css = parseEl.childNodes[0].style; 
while(i--) if(v = css[props[i]]) rules[props[i]] = parse(v); 
return rules; 
}, 
color = function(source,target,pos){ 
var i = 2, j, c, tmp, v = [], r = []; 
while(j=3,c=arguments[i-1],i--) 
if(s(c,0)=='r') { c = c.match(/\d+/g); while(j--) v.push(~~c[j]); } else { 
if(c.length==4) c='#'+s(c,1)+s(c,1)+s(c,2)+s(c,2)+s(c,3)+s(c,3); 
while(j--) v.push(parseInt(s(c,1+j*2,2), 16)); } 
while(j--) { tmp = ~~(v[j+3]+(v[j]-v[j+3])*pos); r.push(tmp<0?0:tmp>255?255:tmp); } 
return 'rgb('+r.join(',')+')'; 
}, 
parse = function(prop){ 
var p = parseFloat(prop), q = prop.replace(/^[\-\d\.]+/,''); 
return isNaN(p) ? { v: q, f: color, u: ''} : { v: p, f: interpolate, u: q }; 
}, 
s = function(str, p, c){ 
return str.substr(p,c||1);//color 用 
}, 
interpolate =function(source,target,pos){ 
return (source+(target-source)*pos).toFixed(3); 
}, 
flower = function(el, style,opts,after){ 
var el = document.getElementById(el), //通过id获取元素对象 
opts = opts || {}, 
target = normalize(style), 
comp = el.currentStyle ? el.currentStyle : getComputedStyle(el, null), //ie和w3c兼容,获取样式 
prop, 
current = {}, 
start = +new Date, //开始时间 
dur = opts.duration||200, //执行事件,默认为200 
finish = start+dur, //结束时间 
interval, 
easing = opts.easing || function(pos){ return (-Math.cos(pos*Math.PI)/2) + 0.5; }; 
for(prop in target) current[prop] = parse(comp[prop]); 
interval = setInterval(function(){ 
var time = +new Date, 
pos = time>finish ? 1 : (time-start)/dur; 
for(prop in target){ 
el.style[prop] = target[prop].f(current[prop].v,target[prop].v,easing(pos)) + target[prop].u; 
} 
if(time>finish) { 
clearInterval(interval); opts.after && opts.after(); after && setTimeout(after,1); 
} 
},10); 
}; 
$[name] = flower; 
})(window,"flower");

var parse = function(prop){ 
var p = parseFloat(prop), q = prop.replace(/^[\-\d\.]+/,''); 
return isNaN(p) ? { v: q, f: color, u: ''} : { v: p, f: interpolate, u: q }; 
} 
var p = parseFloat(prop) 意思是 : 500px => 500; 
q = prop.replace(/^[\-\d\.]+/,''); 500px => px; 
return isNaN(p) ? { v: q, f: color, u: ''} : { v: p, f: interpolate, u: q }; 意思是 如果取的是颜色值(因为带有#号),返回{ v: q, f: color, u: ''} u 代表代为,f是一个color函数(后面会讲到); 
var s = function(str, p, c){ return str.substr(p,c||1); }

s 函数是用来截取字符串,并将最后结果返回
color 函数 将颜色值,最后统一返回 "rgb(x,x,x)" 的形式
normalize 函数 返回一个json对象,对象里包含了该元素要执行的css属性名和值
while(i--) if(v = css[props[i]]) rules[props[i]] = parse(v);
把一行代码拆开,看看到底如何作用
while(i--){
//这里用了一个 =号, 先进行赋值运算,如果不存在之 if将不通过, 一举两得 : )
if(v = css[props[i]]){
rules[props[i]] = parse(v); //赋给新的对象,
}
}
interpolate函数中 return (source+(target-source)*pos).toFixed(3);
toFixed 是为了解决小数问题,如 0.000000001; 会变成 1e-9; 不是我们想要的结果,通过toFixed 可以解决, toFixed (n), 其中n代表保留小数点后几位
el.currentStyle ? el.currentStyle : getComputedStyle(el, null);
这个其实兼容多浏览器,获取元素的一句代码 具体参考 : JS 获取最终样式 【getStyle】
flower的 4个参数 el 目标对象,style 是最终样式,opts,是参数选项包括 (dur时间,easing缓懂函数,after结束后运行的callbak) ,第4个after是最后执行的callbak;
opts.easing 可以利用各种缓动算法,来改变元素的运动状态;

function bounce(pos) { 
if (pos < (1/2.75)) { 
return (7.5625*pos*pos); 
} else if (pos < (2/2.75)) { 
return (7.5625*(pos-=(1.5/2.75))*pos + .75); 
} else if (pos < (2.5/2.75)) { 
return (7.5625*(pos-=(2.25/2.75))*pos + .9375); 
} else { 
return (7.5625*(pos-=(2.625/2.75))*pos + .984375); 
} 
} 
(function($,name){ 
window.flower = flower; 
})(window,'flower');

这样其实就是让内部函数自由,并且只通过这个调用去暴露一个接口。不然外面的函数,访问不到匿名函授中的flower;
看一下调用的例子 : )
<div id="test1" style="position:absolute;left:0px;background:#f00;opacity:0">test</div> 
<div id="test2" style="border:0px solid #00ff00;position:absolute;left:0px;top:400px;background:#0f0">test</div> 
<script> 
(function($,name){ 
var parseEl = document.createElement('div') 
, 
props = ('backgroundColor borderBottomColor borderBottomWidth borderLeftColor borderLeftWidth '+ 
'borderRightColor borderRightWidth borderSpacing borderTopColor borderTopWidth bottom color fontSize '+ 
'fontWeight height left letterSpacing lineHeight marginBottom marginLeft marginRight marginTop maxHeight '+ 
'maxWidth minHeight minWidth opacity outlineColor outlineOffset outlineWidth paddingBottom paddingLeft '+ 
'paddingRight paddingTop right textIndent top width wordSpacing zIndex').split(' ') 
, 
normalize =function (style){ 
var css, 
rules = {}, 
i = props.length, 
v; 
parseEl.innerHTML = '<div style="'+style+'"></div>'; 
css = parseEl.childNodes[0].style; 
while(i--) if(v = css[props[i]]) rules[props[i]] = parse(v); 
return rules; 
}, 
color = function(source,target,pos){ 
var i = 2, j, c, tmp, v = [], r = []; 
while(j=3,c=arguments[i-1],i--) 
if(s(c,0)=='r') { c = c.match(/\d+/g); while(j--) v.push(~~c[j]); } else { 
if(c.length==4) c='#'+s(c,1)+s(c,1)+s(c,2)+s(c,2)+s(c,3)+s(c,3); 
while(j--) v.push(parseInt(s(c,1+j*2,2), 16)); } 
while(j--) { tmp = ~~(v[j+3]+(v[j]-v[j+3])*pos); r.push(tmp<0?0:tmp>255?255:tmp); } 
return 'rgb('+r.join(',')+')'; 
}, 
parse = function(prop){ 
var p = parseFloat(prop), q = prop.replace(/^[\-\d\.]+/,''); 
return isNaN(p) ? { v: q, f: color, u: ''} : { v: p, f: interpolate, u: q }; 
}, 
s = function(str, p, c){ 
return str.substr(p,c||1); 
}, 
interpolate =function(source,target,pos){ 
return (source+(target-source)*pos).toFixed(3); 
}, 
flower = function(el, style,opts,after){ 
var el = document.getElementById(el), 
opts = opts || {}, 
target = normalize(style), 
comp = el.currentStyle ? el.currentStyle : getComputedStyle(el, null), 
prop, 
current = {}, 
start = +new Date, 
dur = opts.duration||200, 
finish = start+dur, 
interval, 
easing = opts.easing || function(pos){ return (-Math.cos(pos*Math.PI)/2) + 0.5; }; 
for(prop in target) current[prop] = parse(comp[prop]); 
interval = setInterval(function(){ 
var time = +new Date, 
pos = time>finish ? 1 : (time-start)/dur; 
for(prop in target){ 
el.style[prop] = target[prop].f(current[prop].v,target[prop].v,easing(pos)) + target[prop].u; 
} 
if(time>finish) { 
clearInterval(interval); opts.after && opts.after(); after && setTimeout(after,1); 
} 
},10); 
}; 
$[name] = flower; 
})(window,"flower"); 
(function(){ 
var bounce = function(pos) { 
if (pos < (1/2.75)) { 
return (7.5625*pos*pos); 
} else if (pos < (2/2.75)) { 
return (7.5625*(pos-=(1.5/2.75))*pos + .75); 
} else if (pos < (2.5/2.75)) { 
return (7.5625*(pos-=(2.25/2.75))*pos + .9375); 
} else { 
return (7.5625*(pos-=(2.625/2.75))*pos + .984375); 
} 
} 
flower('test2', 'left:300px;padding:10px;border:50px solid #ff0000', { 
duration: 1500, 
after: function(){ 
flower('test1', 'background:#0f0;left:100px;padding-bottom:100px;opacity:1', { 
duration: 1234, easing: bounce 
}); 
} 
}); 
})(); 
</script>

参考 : http://scripty2.com/doc/scripty2%20fx/s2/fx/transitions.html
PHP 相关文章推荐
Discuz 5.0 中读取纯真IP数据库函数分析
Mar 16 PHP
PHP SPL标准库之接口(Interface)详解
May 11 PHP
如何使用php实现评委评分器
Jul 31 PHP
PHP连接数据库实现注册页面的增删改查操作
Mar 27 PHP
YII2 实现多语言配置的方法分享
Jan 11 PHP
PHP+Ajax无刷新带进度条图片上传示例
Feb 08 PHP
thinkPHP5.0框架整体架构总览【应用,模块,MVC,驱动,行为,命名空间等】
Mar 25 PHP
详解PHP防止盗链防止迅雷下载的方法
Apr 26 PHP
PHP如何根据文件头检测文件类型实例代码
Oct 14 PHP
解决Laravel5.5下的toArray问题
Oct 15 PHP
laravel接管Dingo-api和默认的错误处理方式
Oct 25 PHP
利用ajax+php实现商品价格计算
Mar 31 PHP
php 验证码实例代码
Jun 01 #PHP
php trim 去除空字符的定义与语法介绍
May 31 #PHP
phpmyadmin 3.4 空密码登录的实现方法
May 29 #PHP
Discuz!下Memcache缓存实现方法
May 28 #PHP
备份mysql数据库的php代码(一个表一个文件)
May 28 #PHP
php下将图片以二进制存入mysql数据库中并显示的实现代码
May 27 #PHP
php set_time_limit(0) 设置程序执行时间的函数
May 26 #PHP
You might like
PHP 文件上传全攻略
2010/04/28 PHP
PHP中each与list用法分析
2016/01/08 PHP
解析WordPress中控制用户登陆和判断用户登陆的PHP函数
2016/03/01 PHP
php微信公众号开发之答题连闯三关
2018/10/20 PHP
Laravel监听数据库访问,打印SQL的例子
2019/10/24 PHP
js表格分页实现代码
2009/09/18 Javascript
javascript当中的代码嗅探扩展原生对象和原型(prototype)
2013/01/11 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
js实现每日自动换一张图片的方法
2015/05/04 Javascript
JS组件中bootstrap multiselect两大组件较量
2016/01/26 Javascript
js+canvas绘制矩形的方法
2016/01/28 Javascript
JS中多种方式创建对象详解
2016/03/22 Javascript
Bootstrap carousel轮转图的使用实例详解
2016/05/17 Javascript
JavaScript面向对象编写购物车功能
2016/08/19 Javascript
微信公众平台开发教程(四) 实例入门:机器人回复(附源码)
2016/12/02 Javascript
使用3D引擎threeJS实现星空粒子移动效果
2020/09/13 Javascript
Bootstrap实现的表格合并单元格示例
2018/02/06 Javascript
Bootstrap导航菜单点击后无法自动添加active的处理方法
2018/08/10 Javascript
原生js实现购物车功能
2020/09/23 Javascript
[01:30]我们共输赢 完美世界城市挑战赛开启全新赛季
2019/04/19 DOTA
[01:03:33]Alliance vs TNC 2019国际邀请赛小组赛 BO2 第一场 8.16
2019/08/18 DOTA
Python实现将文本生成二维码的方法示例
2017/07/18 Python
对python抓取需要登录网站数据的方法详解
2018/05/21 Python
python 内置模块详解
2019/01/01 Python
python的内存管理和垃圾回收机制详解
2019/05/18 Python
Python 寻找局部最高点的实现
2019/12/05 Python
Python字典添加,删除,查询等相关操作方法详解
2020/02/07 Python
Selenium执行完毕未关闭chromedriver/geckodriver进程的解决办法(java版+python版)
2020/12/07 Python
美国一家著名的儿童鞋制造商:Stride Rite
2017/01/02 全球购物
城野医生官方海外旗舰店:风靡亚洲毛孔收敛水
2018/04/26 全球购物
英国家用电器折扣网站:Electrical Discount UK
2018/09/17 全球购物
武汉世纪畅想数字传播有限公司.NET笔试题
2014/07/22 面试题
自我鉴定范文300字
2013/10/01 职场文书
放飞理想主题班会
2015/08/14 职场文书
小学三年级语文教学反思
2016/03/03 职场文书
python语言中pandas字符串分割str.split()函数
2022/08/05 Python