js实现动画效果
2015-11-25 13:13
567 查看
用js实现动画效果的主要思想是利用setInterval()函数.此函数可按照指定的周期(以毫秒计)来调用函数或表达式,并且该方法会不停地调用函数,直到clearInterval()被调用或窗口被关闭。由setInterval()返回的ID值可用作clearInterval()方法的参数。
实现当鼠标在元素上移动时,使元素从左向右移动的效果
本例所实现的功能时,当鼠标移动到三个li元素中的一个时,其宽度从200px变为500px,移出时宽度从500px变为200px
当li元素中没有边框和内边距样式时,此方法有效,但当含有边框和内边距样式时,由于offsetWidth属性包含元素的宽度、内边距和元素的边框,其运行后的元素宽度和预定的宽度不同,为了解决这个问题,我们需要将offsetWidth属性变改为width属性,但是当width属性不是在行内样式定义时,获取width属性值需要调用currentStyle方法(IE)或getComputedStyle()方法(火狐和Chrome)。本文假设为li元素设置了边框属性,相关代码如下
1.单个元素匀速运动
以匀速水平方向运动的元素为例,该方法传入三个参数,分别为要移动元素,要移动到的目标和移动的速度。其中,若速度大于0,表示元素从左向右移动;若速度小于0,表示元素从右向左移动function startMove(ele,iTarget,speed){ var timer=null; clearInterval(timer);//防止方法重复执行时,计时器的重复使用 timer=setInterval(function(){ if(ele.offsetLeft!=iTarget){ ele.style.left=ele.offsetLeft+speed+"px";} },100); }
实现当鼠标在元素上移动时,使元素从左向右移动的效果
var move=document.getElementById("move"); move.onmousemove=function(){startMove(move,500,10);}
2.单个元素透明度的匀速变化
设元素的初始透明度为opacity:0.3或filter:alpha(opacity:30),透明度匀速变化的方法如下function startOpacity(ele,iTarget,speed){ var timer=null; var alpha=30;//元素透明度的值获取较难,这里直接给出 clearInterval(timer); timer=setInterval(function(){ if(alpha!=iTarget){ alpha+=speed; ele.style.filter='alpha(opacity:'+alpha+')'; //设置IE的透明度 ele.style.opacity= alpha/100; //设置fierfox等透明度,注意透明度值是小数 } },50); }实现当鼠标在元素上移动时,使元素透明度从0.3变为1,或从30变为100
var move=document.getElementById("move"); move.onmousemove=function(){ startOpacity(move,100,10);}
3.单个元素的缓冲运动
缓冲运动的本质是速度的不断变化,元素运动时越靠近目标其速度越小,实现方法如下function bufferMove(ele,iTarget){ var timer=null; clearInterval(timer); timer=setInterval(function(){ var speed=(iTarget-ele.offsetLeft)/200; if(speed>0){ speed=Math.ceil(speed);//避免速度值出现小数的状况,因为元素有关的像素值必须为整数 speed=Math.floor(speed); } if(ele.offsetLeft!=iTarget){ ele.style.left=ele.offsetLeft+speed+"px";} },100); }实现当鼠标在元素上移动时,元素做缓冲运动到达目标值
var move=document.getElementById("move"); move.onmousemove=function(){ bufferMove(move,500); }
4.多物体的缓冲运动
多物体的运动需要注意的是物体之间公共的变量或计时器,为了防止多物体之间的共用,需要将物体之共用的部分私有化本例所实现的功能时,当鼠标移动到三个li元素中的一个时,其宽度从200px变为500px,移出时宽度从500px变为200px
var container=document.getElementById("container"); var iLi=container.getElementsByTagName("li"); for(var i=0,length=iLi.length;i<length;i++){ iLi[i].timer=null;//将计时器私有 iLi[i].onmouseover=function(){ bufferMove(this,500);//注意,这里用到了闭包的知识,this并不等于iLi[i],因为变量i即使bufferMove的活动对象,同时也是其父方法的活动对象,二者共用一个内存空间,所以如果在这里用<span style="font-family: Arial, Helvetica, sans-serif;">iLi[i],该值就相当于iLi[3]</span> } iLi[i].onmouseout=function(){ bufferMove(this,200); } } function bufferMove(ele,iTarget){ clearInterval(ele.timer); ele.timer=setInterval(function(){ var speed=(iTarget-ele.offsetWidth)/10; if(speed>0){ speed=Math.ceil(speed); }else{ speed=Math.floor(speed); } if(ele.offsetWidth!=iTarget){ ele.style.width=ele.offsetWidth+speed+"px";} },100); }
当li元素中没有边框和内边距样式时,此方法有效,但当含有边框和内边距样式时,由于offsetWidth属性包含元素的宽度、内边距和元素的边框,其运行后的元素宽度和预定的宽度不同,为了解决这个问题,我们需要将offsetWidth属性变改为width属性,但是当width属性不是在行内样式定义时,获取width属性值需要调用currentStyle方法(IE)或getComputedStyle()方法(火狐和Chrome)。本文假设为li元素设置了边框属性,相关代码如下
function getStyle(ele,attr){ if(ele.currentStyle){ return ele.currentStyle[attr]; }else{ return getComputedStyle(ele,false)[attr]; } } var container=document.getElementById("container"); var iLi=container.getElementsByTagName("li"); for(var i=0,length=iLi.length;i<length;i++){ iLi[i].timer=null; iLi[i].onmouseover=function(){ bufferMove(this,500); } iLi[i].onmouseout=function(){ bufferMove(this,200); } } function bufferMove(ele,iTarget){ clearInterval(ele.timer); ele.timer=setInterval(function(){ var speed=(iTarget-parseInt(getStyle(ele,"width")))/10; if(speed>0){ speed=Math.ceil(speed); }else{ speed=Math.floor(speed); } if(parseInt(getStyle(ele,"width"))!=iTarget){ ele.style.width=parseInt(getStyle(ele,"width"))+speed+"px";} },100); }
编写方法,使该方法能够对不同的元素的不同属性改变,以产生运动效果。该方法传入三个值,分别为要操作的元素、要操作的元素属性和属性的目标值,由于透明度的属性值与其他属性值不同,需要单独考虑
function bufferMove(ele,attr,iTarget){
clearInterval(ele.timer);
ele.timer=setInterval(function(){
console.log(ele);
//获取当前的属性值
var icur=0;
if(attr=="opacity"){
icur=Math.round(parseFloat(getStyle(ele,attr))*100);
}else{
icur=parseInt(getStyle(ele,attr));
}
var speed=(iTarget-icur)/2;
if(speed>0){
speed=Math.ceil(speed);
}else{
speed=Math.floor(speed);
}
if(icur==iTarget){
clearInterval(ele.timer);
}else{
if(attr=="opacity"){
ele.style[attr]=(icur+speed)/100;
ele.style.filter="filter:alpha(opacity"+(icur+speed)+")";
console.log(getStyle(ele,"opacity"));
console.log(speed);
}else{
ele.style[attr]=icur+speed+"px";}
}},50);
}
5. 多物体的链式运动
链式运动就是元素一次运动完成后,随后触发第二次运动。
for(var i=0,length=iLi.length;i<length;i++){
iLi[i].timer=null;
iLi[i].icur=0;
iLi[i].onmouseover=function(){
bufferMove(this,"opacity",100,function(){
bufferMove(this,"height",100);
})
}
iLi[i].onmouseout=function(){
bufferMove(this,"height",80,function(){
bufferMove(this,"opacity",30)
});
}
}
function bufferMove(ele,attr,iTarget,fn){
clearInterval(ele.timer);
ele.timer=setInterval(function(){
//获取当前的属性值
if(attr=="opacity"){
ele.icur=Math.round(parseFloat(getStyle(ele,attr))*100);
}else{
ele.icur=parseInt(getStyle(ele,attr));
}
var speed=(iTarget-ele.icur)/2;
if(speed>0){
speed=Math.ceil(speed);
}else{
speed=Math.floor(speed);
}
if(ele.icur==iTarget){
clearInterval(ele.timer);
//传入返回的ele元素,实现函数的回调
if(fn){fn.call(ele);}
}else{
if(attr=="opacity"){
ele.style[attr]=(ele.icur+speed)/100;
ele.style.filter="filter:alpha(opacity"+(ele.icur+speed)+")";
}else{
ele.style[attr]=ele.icur+speed+"px";}
}},50);
return ele;
}
6 多物体同时运动
多物体同时运动,需引入json
<span style="font-size:12px;font-weight: normal;">var container=document.getElementById("container");
var iLi=container.getElementsByTagName("li");
for(var i=0,length=iLi.length;i<length;i++){
iLi[i].timer=null;
iLi[i].onmouseover=function(){
bufferMove(this,{opacity:100,height:81});
}
iLi[i].onmouseout=function(){
bufferMove(this,{height:80,opacity:30});
}
}
function bufferMove(ele,json,fn){
var flag=true;
clearInterval(ele.timer);
ele.timer=setInterval(function(){
//获取当前的属性值
for(var attr in json){
if(attr=="opacity"){
ele.icur=Math.round(parseFloat(getStyle(ele,attr))*100);
}else{
ele.icur=parseInt(getStyle(ele,attr));
}
var speed=(json[attr]-ele.icur)/2;
if(speed>0){
speed=Math.ceil(speed);
}else{
speed=Math.floor(speed);
}
if(ele.icur!=json[attr]){
flag=false;
}
if(attr=="opacity"){
ele.style[attr]=(ele.icur+speed)/100;
ele.style.filter="filter:alpha(opacity"+(ele.icur+speed)+")";
}else{
ele.style[attr]=ele.icur+speed+"px";
}
if (flag) {
clearInterval(ele.timer);
//回调函数
if(fn){fn.call(ele);}
} }},50);
return ele;
}</span>
相关文章推荐
- fastJson解析
- js插件的经典写法与总结
- 返回Json数据浏览器带上<pre></pre>标签解决方法
- js 连接地址分析
- javascript下ie7,ie8的Date Bug的解决
- JavaScript的this词法(二)
- javascript 基础教程[温故而知新一]
- WCF 自托管、无配置文件实现jsonp(跨域)的访问
- highChartsjs饼状图
- ExtJS中的全局变量的保存和使用
- DIV滚动条到底部判断且自动加载,到上限更多选项
- JSON
- javascript定义对象写法
- [javascript]DOM基础
- jsp内置对象作业2-留言簿
- JavaScript设置组件不可见三种方式:display、visibility、opacity
- js两种post方法
- 使用flot.js 发现x轴y轴无法显示轴名称
- JavaScript的作用域链的理解
- javascript图片预加载