javascript 小型动画组件与实现代码
程序员文章站
2022-06-06 22:02:44
做一个普通的动画效果,js是怎么完成的呢.看一下例子 复制代码 代码如下: setinterval(function(){ element.style.left =pars...
做一个普通的动画效果,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
复制代码 代码如下:
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
上一篇: 新网站在建设时需要注意的几点问题
下一篇: tomcat源码研究之参数编码格式处理