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 相关文章推荐
PHPUnit PHP测试框架安装方法
Mar 23 PHP
解析php中var_dump,var_export,print_r三个函数的区别
Jun 21 PHP
解决cPanel无法安装php5.2.17
Jun 22 PHP
ThinkPHP分组下自定义标签库实例
Nov 01 PHP
php为字符串前后添加指定数量字符的方法
May 04 PHP
ThinkPHP3.2.2实现持久登录(记住我)功能的方法
May 16 PHP
thinkphp中的url跳转用法分析
Jul 12 PHP
浅谈PHP中静态方法和非静态方法的相互调用
Oct 04 PHP
PHP实现一维数组与二维数组去重功能示例
May 24 PHP
PHP设计模式之工厂模式(Factory Pattern)的讲解
Mar 21 PHP
php常用经典函数集锦【数组、字符串、栈、队列、排序等】
Aug 23 PHP
Yii框架 session 数据库存储操作方法示例
Nov 18 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
MySQL修改密码方法总结
2008/03/25 PHP
通过PHP CLI实现简单的数据库实时监控调度
2009/07/01 PHP
PHP 显示客户端IP与服务器IP的代码
2010/10/12 PHP
PHP错误和异长常处理总结
2014/03/06 PHP
网站防止被刷票的一些思路与方法
2015/01/08 PHP
typecho插件编写教程(六):调用接口
2015/05/28 PHP
JQuery 简便实现页面元素数据验证功能
2007/03/24 Javascript
Prototype源码浅析 String部分(二)
2012/01/16 Javascript
javascript记录文本框内文字个数检测文字个数变化
2014/10/14 Javascript
javascript拖拽效果延伸学习
2016/04/04 Javascript
最原始的jQuery注册验证方式
2016/10/11 Javascript
jQuery实现返回顶部按钮和scroll滚动功能[带动画效果]
2017/07/05 jQuery
vue父子组件的嵌套的示例代码
2017/09/08 Javascript
jQuery实现IE输入框完成placeholder标签功能的方法
2017/09/20 jQuery
jQuery实现获取table中鼠标click点击位置行号与列号的方法
2017/10/09 jQuery
基于vue 动态加载图片src的解决方法
2018/02/05 Javascript
使用Vue-Awesome-Swiper实现旋转叠加轮播效果&amp;平移轮播效果
2019/08/16 Javascript
jqGrid表格底部汇总、合计行footerrow处理
2019/08/21 Javascript
python实现简单的socket server实例
2015/04/29 Python
Python抓取淘宝下拉框关键词的方法
2015/07/08 Python
Python数据分析之双色球统计两个红和蓝球哪组合比例高的方法
2018/02/03 Python
Python iter()函数用法实例分析
2018/03/17 Python
PyQt4实现下拉菜单可供选择并打印出来
2018/04/20 Python
Python实现钉钉发送报警消息的方法
2019/02/20 Python
python构造IP报文实例
2020/05/05 Python
利用django创建一个简易的博客网站的示例
2020/09/29 Python
html5实现完美兼容各大浏览器的播放器
2014/12/26 HTML / CSS
利用HTML5 Canvas制作键盘及鼠标动画的实例分享
2016/03/15 HTML / CSS
新西兰优惠网站:Treat Me
2019/07/04 全球购物
医学检验专业大学生求职信
2013/11/18 职场文书
预备党员思想汇报
2014/01/08 职场文书
企业承诺书格式
2014/05/21 职场文书
汽车维修专业自荐书
2014/05/26 职场文书
自我检讨书范文
2015/01/28 职场文书
2015年体检中心工作总结
2015/05/27 职场文书
2019年最新七夕唯美祝福语(60条)
2019/07/22 职场文书