首页 > 代码库 > 原生js动画效果(源码解析)

原生js动画效果(源码解析)

在做页面中,多数情况下都会遇到页面上做动画效果,我们大部分做动画的时候都是使用框架来做(比如jquery),这里我介绍下如何让通过原生的js来实现像框架一样的动画效果!

1、匀速动画效果

说明:匀速动画就是动画的效果从开始到结束每次执行的速度都是一致的

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>匀速动画</title><style type="text/css">   html,body{margin:0;padding:0;}   div{margin:0;padding:0;}  .odiv{width:200px; height:200px; background:#f00; position:relative; left:-200px; top:100px;}  .sdiv{width:20px; height:60px; background:#00f; position:absolute; top:70px; right:-20px;}</style></head><body><div id="odiv" class="odiv">    <div id="sdiv" class="sdiv">    </div></div></body></html><script language="javascript">window.onload = function(){    var odiv = document.getElementById(odiv);    odiv.onmouseover = function(){       startMover(0);    }    odiv.onmouseout = function(){       startMover(-200);    }}var timer = null;function startMover(itarget){//目标值    clearInterval(timer);//执行当前动画同时清除之前的动画    var odiv = document.getElementById(odiv);    timer = setInterval(function(){    var speed = 0;    if(odiv.offsetLeft > itarget){       speed = -1;    }    else{       speed = 1;    }    if(odiv.offsetLeft == itarget){       clearInterval(timer);    }    else{        odiv.style.left = odiv.offsetLeft+speed+px;        }    },30);}//注明:offsetWidth = width+padding+border//offsetHeight = height+padding+border//offsetWidth=(border-width)*2+(padding-left)+(width)+(padding-right)//offsetHeight=(border-width)*2+(padding-top)+(height)+(padding-bottom)/*offsetLeft=(offsetParent的padding-left)+(中间元素的offsetWidth)+(当前元素的margin-left)。offsetTop=(offsetParent的padding-top)+(中间元素的offsetHeight)+(当前元素的margin-top)。当offsetParent为body时情况比较特殊:在IE8/9/10及Chrome中,offsetLeft = (body的margin-left)+(body的border-width)+(body的padding-left)+(当前元素的margin-left)。在FireFox中,offsetLeft = (body的margin-left)+(body的padding-left)+(当前元素的margin-left)。offsetParent属性返回一个对象的引用,这个对象是距离调用offsetParent的元素最近的(在包含层次中最靠近的),并且是已进行过CSS定位的容器元素。 如果这个容器元素未进行CSS定位, 则offsetParent属性的取值为根元素的引用。总的来说两条规则:1、如果当前元素的父级元素没有进行CSS定位(position为absolute或relative),offsetParent为body。2、如果当前元素的父级元素中有CSS定位(position为absolute或relative),offsetParent取最近的那个父级元素。*/</script>

 2、缓冲动画

说明:缓冲动画就是动画到结束或这开始的时候,速度是随着动画执行的进度动态变化的

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>缓冲动画</title><style type="text/css">   html,body{margin:0;padding:0;}   div{margin:0;padding:0;}  .odiv{width:200px; height:200px; background:#f00; position:relative; left:-200px; top:100px;}  .sdiv{width:20px; height:60px; background:#00f; position:absolute; top:70px; right:-20px;}</style></head><body><div id="odiv" class="odiv">    <div id="sdiv" class="sdiv">    </div></div></body></html><script language="javascript">window.onload = function(){    var odiv = document.getElementById(odiv);    odiv.onmouseover = function(){       startMover(0);    }    odiv.onmouseout = function(){       startMover(-200);    }}var timer = null;function startMover(itarget){//速度和目标值    clearInterval(timer);//执行当前动画同时清除之前的动画    var odiv = document.getElementById(odiv);    timer = setInterval(function(){    var speed = (itarget-odiv.offsetLeft)/10;//缓冲动画的速度参数变化值    //如果速度是大于0,说明是向右走,那么就向上取整    speed = speed>0?Math.ceil(speed):Math.floor(speed);    //Math.floor();向下取整    if(odiv.offsetLeft == itarget){       clearInterval(timer);    }    else{        //clientLeft 返回对象的offsetLeft属性值和到当前窗口左边的真实值之间的距离         odiv.style.left = odiv.offsetLeft+speed+px;        }    },30);}</script>

3、透明度动画

说明:处理元素透明效果的动画

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>透明度动画</title><style type="text/css">   html,body{margin:0;padding:0;}   div{margin:0;padding:0;}  .odiv{width:200px; height:200px; background:#f00; position:relative; left:0px; top:100px;opacity:0.3; filter:alpha(opacity:30); float:left; margin:10px;}</style></head><body><div id="odiv" class="odiv"></div></body></html><script language="javascript">window.onload = function(){    var odiv = document.getElementsByTagName(div);    for(var i=0;i<odiv.length;i++)    {          odiv[i].onmouseover = function(){           startOP(this,100);        }        odiv[i].onmouseout = function(){           startOP(this,30);        }        odiv[i].timer = null;//事先定义        odiv[i].alpha = null;//事先定义        //这里发现一个问题,对象的动画属性可以不定义,但是透明度属性必须定义,否则报错    }}function startOP(obj,utarget){     clearInterval(obj.timer);//先关闭定时器     obj.timer = setInterval(function(){     var speed = 0;     if(obj.alpha>utarget){        speed = -10;     }     else{        speed = 10;     }     obj.alpha = obj.alpha+speed;     if(obj.alpha == utarget){        clearInterval(obj.timer);     }     obj.style.filter = alpha(opacity:+obj.alpha+);//基于IE的     obj.style.opacity = parseInt(obj.alpha)/100;     },30); }</script>

4、多物体动画

说明:多个物体在一起执行的动画效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>多物体动画</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;}.odiv ul li{width:200px; height:100px; background:yellow; margin-bottom:20px;}</style></head><body><div id="odiv" class="odiv">    <ul>        <li></li>        <li></li>        <li></li>    </ul></div></body></html><script language="javascript">window.onload = function(){    var olist = document.getElementsByTagName(li);    for(var i=0; i<olist.length;i++)    {      olist[i].onmouseover = function(){        startmov(this,400);      };      olist[i].onmouseleave = function(){        startmov(this,200);      };      olist[i].timer = null;    }    function startmov(obj,itarget){       clearInterval(obj.timer);//执行动画之前清除动画       obj.timer = setInterval(function(){          var speed =0;          speed = (itarget - obj.offsetWidth)/8;          speed = speed>0?Math.ceil(speed):Math.floor(speed);          if(obj.offsetWidth == itarget){           clearInterval(obj.timer);          }          else{          obj.style.width = obj.offsetWidth+speed+px;          }       },30);    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>
View Code

5、获取样式动画

说明:这里的获取样式是通过计算出来元素的样式,然后通过这个计算出来的结果来操作元素

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>样式动画</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;width:200px; height:200px; border:2px solid #000; background:red; font-size:20px;}</style></head><body><div id="odiv" class="odiv">  hjshfjdfsdfhsdj</div></body></html><script language="javascript">/*currentStyle:获取计算后的样式,也叫当前样式、最终样式。优点:可以获取元素的最终样式,包括浏览器的默认值,而不像style只能获取行间样式,所以更常用到。注意:不能获取复合样式如background属性值,只能获取单一样式如background-color等。alert (oAbc.currentStyle);非常遗憾的是,这个好使的东西也不能被各大浏览器完美地支持。准确地说,在我测试的浏览器中,IE8和Opera 11弹出了“object CSSStyleDeclaration”;FF 12、chrome 14、safari 5则弹出“undefined”。虽然currentStyle无法适用于所有浏览器,但是可以根据以上测试的结果来区分开支持、不支持的浏览器,然后再找到兼容的写法。var oAbc = document.getElementById("abc");if(oAbc.currentStyle) {        //IE、Opera        alert("我支持currentStyle");} else {        //FF、chrome、safari        alert("我不支持currentStyle");}其实在FF浏览器中我们可以使用getComputedStyle(obj,false)来达到与IE下currentStyle相同的效果。getComputedStyle(obj,false):在FF新版本中只需要第一个参数,即操作对象,第二个参数写“false”也是大家通用的写法,目的是为了兼容老版本的火狐浏览器。兼容写法:var oAbc = document.getElementById("abc");if(oAbc.currentStyle) {        //IE、Opera        //alert("我支持currentStyle");        alert(oAbc.currentStyle.width);} else {        //FF、chrome、safari        //alert("我不支持currentStyle");        alert(getComputedStyle(oAbc,false).width);}一个空白页面中body的id=”abc”,测试以上代码,IE和Opera弹出“auto”,其它三款浏览器则弹出“***px”。虽然结果不同,但是可以发现chrome和safari也都和火狐一样,顺利地读取到了属性值。不支持currentStyle的三款浏览器(FF、chrome、safari),都是支持getComputedStyle的。结果表明:对浏览器是否支持currentStyle的判断 + getComputedStyle,就可以做到兼容各主流浏览器的效果。而且兼容写法并不复杂,你掌握了吗?^_^支持currentStyle:IE、Opera支持getComputedStyle:FireFox、Chrome、Safari注意最后的弹出内容,currentStyle返回浏览器的默认值”auto”,而getComputedStyle则返回具体的值”**px”。这应该是两者的一个小差异,有兴趣的童鞋可以一起交流研究下。*/window.onload = function(){    var odiv = document.getElementById(odiv);    odiv.onmouseover = function(){       startMov(this);    };    function startMov(obj){       setInterval(function(){        obj.style.width = parseInt(getStyle(obj,width))+1+px;        obj.style.fontSize = parseInt(getStyle(obj,fontSize))+1+px;       },30);    }    function getStyle(obj,attr)    {      if(obj.currentStyle){        return obj.currentStyle[attr];      }      else{        return getComputedStyle(obj,false)[attr];      }    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>
View Code

 6、多物体复杂动画

说明:多物体复杂动画可以控制元素的不同属性变化来实现动画效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>多物体复杂动画</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;}.odiv ul li{width:200px; height:100px; background:yellow; margin-bottom:20px; border:2px solid #000;}</style></head><body><div id="odiv" class="odiv">    <ul>        <li id="li1"></li>        <li id="li2"></li>    </ul></div></body></html><script language="javascript">window.onload = function(){    var li1 = document.getElementById(li1);    var li2 = document.getElementById(li2);    li1.onmouseover = function(){       startMov(this,400,width);    };    li1.onmouseout = function(){       startMov(this,200,width);    };    li2.onmouseover = function(){       startMov(this,200,height);    };    li2.onmouseout = function(){       startMov(this,100,height);    };    function startMov(obj,itarget,attr){       clearInterval(obj.timer);//执行动画之前清除动画       obj.timer = setInterval(function(){          var icur = parseInt(getStyle(obj,attr));          var speed =0;          speed = (itarget - icur)/8;          speed = speed>0?Math.ceil(speed):Math.floor(speed);          if(icur == itarget){           clearInterval(obj.timer);          }          else{          obj.style[attr] = icur+speed+px;          }       },30);    }    function getStyle(obj,attr)    {      if(obj.currentStyle){        return obj.currentStyle[attr];      }      else{        return getComputedStyle(obj,false)[attr];      }    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>
View Code

7、多物体复杂动画(带透明度的)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>多物体复杂动画(带透明度的)</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;}.odiv ul li{width:200px; height:100px; background:yellow; margin-bottom:20px; border:2px solid #000;}#li1{opacity:0.3;filter:alpha(opacity:30);}</style></head><body><div id="odiv" class="odiv">    <ul>        <li id="li1"></li>        <li id="li2"></li>    </ul></div></body></html><script language="javascript">window.onload = function(){    var li1 = document.getElementById(li1);    var li2 = document.getElementById(li2);    li1.onmouseover = function(){       startMov(this,100,opacity);    };    li1.onmouseout = function(){       startMov(this,30,opacity);    };    li2.onmouseover = function(){       startMov(this,200,height);    };    li2.onmouseout = function(){       startMov(this,100,height);    }    li1.timer = null;    li2.timer = null;    function startMov(obj,itarget,attr){       clearInterval(obj.timer);//执行动画之前清除动画       obj.timer = setInterval(function(){          var icur = 0;          if(attr == opacity){            icur = Math.round(parseFloat(getStyle(obj,attr))*100);//转换成整数,并且四舍五入下            //计算机在计算小数的时候往往是不准确的!          }          else{          icur = parseInt(getStyle(obj,attr));          }          var speed =0;          speed = (itarget - icur)/8;          speed = speed>0?Math.ceil(speed):Math.floor(speed);          if(icur == itarget){           clearInterval(obj.timer);          }          else{              if(attr == opacity){                obj.style.filter = alpha(opacity:+(icur+speed)+);                obj.style.opacity = (icur+speed)/100;              }              else{              obj.style[attr] = icur+speed+px;              }           }       },30);    }    function getStyle(obj,attr)    {      if(obj.currentStyle){        return obj.currentStyle[attr];      }      else{        return getComputedStyle(obj,false)[attr];      }    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>
View Code

8、链式动画

说明:链式动画就是当前动画执行完成后执行下一个动画效果

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>链式动画</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;}.odiv ul li{width:200px; height:100px; background:yellow; margin-bottom:20px; border:2px solid #000;}#li1{opacity:0.3;filter:alpha(opacity:30);}</style></head><body><div id="odiv" class="odiv">    <ul>        <li id="li1"></li>    </ul></div></body></html><script language="javascript">window.onload = function(){    var li1 = document.getElementById(li1);    li1.onmouseover = function(){       startMov(li1,400,width,function(){         startMov(li1,200,height,function(){            startMov(li1,100,opacity);         });       });    };    li1.onmouseout = function(){       startMov(li1,30,opacity,function(){         startMov(li1,100,height,function(){            startMov(li1,100,width);         });       });    };    li1.timer = null;    function startMov(obj,itarget,attr,fn){//fn回调函数       clearInterval(obj.timer);//执行动画之前清除动画       obj.timer = setInterval(function(){          var icur = 0;          if(attr == opacity){            icur = Math.round(parseFloat(getStyle(obj,attr))*100);//转换成整数,并且四舍五入下            //计算机在计算小数的时候往往是不准确的!          }          else{          icur = parseInt(getStyle(obj,attr));          }          var speed =0;          speed = (itarget - icur)/8;          speed = speed>0?Math.ceil(speed):Math.floor(speed);          if(icur == itarget){           clearInterval(obj.timer);           if(fn){             fn();            }          }          else{              if(attr == opacity){                obj.style.filter = alpha(opacity:+(icur+speed)+);                obj.style.opacity = (icur+speed)/100;              }              else{              obj.style[attr] = icur+speed+px;              }           }       },30);    }    function getStyle(obj,attr)    {      if(obj.currentStyle){        return obj.currentStyle[attr];      }      else{        return getComputedStyle(obj,false)[attr];      }    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>
View Code

9、多物体同时运动动画(支持链式动画)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><title>多物体同时运动动画</title><style type="text/css">body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,tr,td {margin:0;padding:0; font-size:12px;} table {border-collapse:collapse;border-spacing:0;} fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var {font-style:normal;font-weight:normal} ol,ul {list-style:none} caption,th,td{text-align:center} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal} q:before,q:after {content:‘‘} abbr,acronym { border:0}.odiv{position:relative;}.odiv ul li{width:200px; height:100px; background:yellow; margin-bottom:20px; border:2px solid #000;}#li1{opacity:0.3;filter:alpha(opacity:30);}</style></head><body><div id="odiv" class="odiv">    <ul>        <li id="li1"></li>    </ul></div></body></html><script language="javascript">window.onload = function(){    var li1 = document.getElementById(li1);    li1.onmouseover = function(){       startMov(li1,{width:201,height:200,opacity:100});    };    li1.onmouseout = function(){       startMov(li1,{width:200,height:100,opacity:30});    };    li1.timer = null;    function startMov(obj,json,fn){//fn回调函数       clearInterval(obj.timer);//执行动画之前清除动画       var flag = true;//是否动画都完成了       obj.timer = setInterval(function(){         for(var attr in json){          var icur = 0;          if(attr == opacity){            icur = Math.round(parseFloat(getStyle(obj,attr))*100);//转换成整数,并且四舍五入下            //计算机在计算小数的时候往往是不准确的!          }          else{          icur = parseInt(getStyle(obj,attr));          }          var speed =0;          speed = (json[attr] - icur)/8;          speed = speed>0?Math.ceil(speed):Math.floor(speed);          if(icur != json[attr]){           flag = false;          }          if(attr == opacity){            obj.style.filter = alpha(opacity:+(icur+speed)+);            obj.style.opacity = (icur+speed)/100;          }          else{          obj.style[attr] = icur+speed+px;          }          if(flag){            clearInterval(obj.timer);            if(fn){              fn();            }          }        }       },30);    }    function getStyle(obj,attr)    {      if(obj.currentStyle){        return obj.currentStyle[attr];      }      else{        return getComputedStyle(obj,false)[attr];      }    }}//offsetWidth获取的是元素实际的宽度(包括边框和内边距)//只要是多物体运动,所有的属性都不能共用</script>

最后一个动画效果完善了上述所有动画的代码,自己可以根据上述的代码进行扩展!

课程视频地址:http://www.imooc.com/learn/167

原生js动画效果(源码解析)