卜小娴 2016-10-11
前面我们介绍了Javascript的回到顶部效果,今天呢,我们对Javascript动画做进一步的研究。在这篇博文中我们只介绍简单的匀速运动、简单的缓冲运动和简单的多物体运动后面我们还会介绍任意值变化的运动、链式运动、同时运动,同时我们还会简单的封装一个运动插件并且还会将Javascript方法和jquery方法进行比较。
1、简单的匀速运动
下面我们介绍一个demo,鼠标移入,动画向右移动(即隐藏部分显示);鼠标离开,动画向左运动(继续隐藏)整个过程都是匀速的。有了前面回到顶部效果作为基础,这里主要讲解重要部分,先来看看代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>demo1</title> <style type="text/css"> body,div,span{ margin: 0px; padding: 0px; } #div1{ width: 200px; height: 200px; background: red; position: relative; left: -200px; } #share{ width: 20px; height: 40px; background: blue; position: absolute; left: 200px; top: 75px; } </style> <script type="text/javascript"> //一进来就加载 window.onload = function(){ //获取div var oDiv = document.getElementById('div1'); //鼠标移入时执行函数 oDiv.onmouseover = function(){ startMove(); } //鼠标移出时执行函数 oDiv.onmouseout = function(){ startMove1(); } } //定义一个定时器 var timer = null; function startMove(){ //让它一进来的时候就把计时器清掉,避免后面引入多个计时器 clearInterval(timer); var oDiv = document.getElementById('div1'); //插入一个定时器 timer = setInterval(function(){ // oDiv.style.left = oDiv.offsetLeft+10+'px'; // //offsetLeft 当前left的值 // //此时运行的结果为鼠标移上去后,一直在动,此时需要if进行判断 if(oDiv.offsetLeft == 0){ //当当前的left值为0的时候,清空计时器 clearInterval(timer); } else{ //当当前的left值不为0的时候,进行移动 oDiv.style.left = oDiv.offsetLeft+10+'px'; } },30) } function startMove1(){ clearInterval(timer); var oDiv = document.getElementById('div1'); timer = setInterval(function(){ if(oDiv.offsetLeft == -200){ clearInterval(timer); } else{ oDiv.style.left = oDiv.offsetLeft-10+'px'; } },30) } //可以修改当前内容里面相同的部分 </script> </head> <body> <div id="div1"> <span id="share"> 分享 </span> </div> </body> </html>
在Javascript部分,我们发现有很多代码重复了,这时我们可以通过将不同的地方用参数的方法传进去,主要代码如下:
/* * 前面的onmouseover和onmouseout事件中分别改为 * startMove(10,0); * startMove(-10,-200); * 后面再将 startMove和startMove1两个函数进行合并,代码如下: */ function startMove(speed,iTarget){ clearInterval(timer); var oDiv = document.getElementById('div1'); timer = setInterval(function(){ if(oDiv.offsetLeft == iTarget){ clearInterval(timer); } else{ oDiv.style.left = oDiv.offsetLeft+speed+'px'; } },30) }
此时我们还是会发现一个问题,就是,在功能相同的情况下,参数越少越好,这时我们要对我们之前的代码做进一步修改,因为iTarget是目标值,所以我们考虑将speed参数去掉,代码如下:
//考虑参数越少越好原则,可以去掉speed,同时,前面的onmouseover和onmouseout事件也应相应改变 function startMove(iTarget){ clearInterval(timer); var oDiv = document.getElementById('div1'); timer = setInterval(function(){ //定义一个speed var speed = 0; //对speed进行判断 if(oDiv.offsetLeft > iTarget){ //当oDiv.offsetLeft > iTarget时,应该向左移动 speed = -10; } else{ speed = 10; } if(oDiv.offsetLeft == iTarget){ clearInterval(timer); } else{ oDiv.style.left = oDiv.offsetLeft+speed+'px'; } },30) }
到这里,我们的匀速运动效果基本完成。在上面的demo中,我们改变的是left效果,同理我们还可以改变right,width和height效果。思考:在css3动画中有改变透明度的效果,在这里我们是否可以通过前面的方式来得到实现呢?
答案:大致可以用上面的方法去实现,但是有个小小的问题值得注意,无论是left,right还是width,height它们都有单位px(在上面的demo中,有一行代码就是这样:oDiv.style.left = oDiv.offsetLeft+speed+'px';),而透明度无论是opacity也好,是filter也好,它们都是没有单位的,故我们可以写如下代码:
alpha += speed; oDiv.style.filter = 'alpha(opacity:'+alpha+')'; oDiv.style.opacity = alpha/100;
完整代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>demo2</title> <style type="text/css"> body,div{ margin: 0px; padding: 0px; } #div1{ width: 200px; height: 200px; background: red; filter: alpha(opacity:30); opacity: 0.3; } </style> <script type="text/javascript"> window.onload = function(){ var oDiv = document.getElementById('div1'); oDiv.onmouseover = function(){ startMove(100); //鼠标移入的时候,透明度为100% } oDiv.onmouseout = function(){ startMove(30); //鼠标移出的时候,透明度为30% } } var timer = null; var alpha = 30; function startMove(iTarget){ var oDiv = document.getElementById('div1'); clearInterval(timer); //在运行之前,先关闭定时器 //关了定时器后,现在运行时需要加定时器 timer = setInterval(function(){ var speed = 0; if(alpha > iTarget){ speed = -10; } else{ speed = 10 } if(alpha == iTarget){ clearInterval(timer); } else{ alpha += speed; oDiv.style.filter = 'alpha(opacity:'+alpha+')'; oDiv.style.opacity = alpha/100; } },30) } </script> </head> <body> <div id="div1"> 要求: <p>鼠标移入,透明度为100%;鼠标移出,透明度为30%</p> </div> </body> </html>
到这里,我们的速度动画就告一段落了。关于opacity和filter,详情请见这里
2、缓冲运动
回忆之前回到顶部效果,为了增加用户的体验效果,回到顶部时是先快后慢。有了前面的基础,这里句很好办了,以demo1为例,我们可以添加如下代码:
function startMove(iTarget){ var oDiv = document.getElementById('div1'); clearInterval(timer); timer = setInterval(function(){ var speed = (iTarget - oDiv.offsetLeft)/20; speed = speed>0?Math.ceil(speed):Math.floor(speed); //注意这里的取整问题,不然运动后回不到原来的位置 // if(speed > 0){ // speed = Math.ceil(speed); // } // else{ // speed = Math.floor(speed); // } if(iTarget == oDiv.offsetLeft){ clearInterval(timer); } else{ oDiv.style.left = oDiv.offsetLeft+speed+'px'; } },30) }
在这段代码中,var speed = (iTarget - oDiv.offsetLeft)/20;通过控制被除数可以控制动画的速度,然后我们分别用Math.floor和Math.ceil分别进行向下和向上取整,如果没用取整,那么鼠标移入和移出都达不到想要的效果(计算机在进行计算时总是有误差的)。到这里,缓冲运动也介绍的差不多了。下面我们来介绍多物体运动。
3、多物体运动
有了前面的基础,我们来看多物体运动时就觉得简单了。在多物体运动中,我们将宽度变化和透明度变化分开来讲
【多物体宽度变化】
在多物体宽度变化中,我们用无序列表来实现。与单个物体宽度变化不同的是,我们要用for循环依次遍历我们想要的值,关键代码如下:
var aLi = document.getElementsByTagName('li'); for(var i = 0; i< aLi.length; i++){ //i=0 aLi[i].onmouseover = function(){ startMove(this,400); } aLi[i].onmouseout = function(){ startMove(this,200); } }
全代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>多物体动画</title> <style type="text/css"> body,ul,li{ margin: 0px; padding: 0px; } ul,li{ list-style: none; } ul li{ width: 200px; height: 100px; background: yellow; margin-bottom: 20px; } </style> <script type="text/javascript"> window.onload = function(){ var aLi = document.getElementsByTagName('li'); for(var i = 0; i< aLi.length; i++){ //i=0 aLi[i].timer = null; aLi[i].onmouseover = function(){ startMove(this,400);//this指向当前的aLi[i].onmouseover事件 } aLi[i].onmouseout = function(){ startMove(this,200);//this指向当前的aLi[i].onmouseout事件 } } } //var timer = null; /* * 若该代码还是在这里,当鼠标依次缓慢经过时不会出现大的问题,但是当移动的速度比较快时,会发现有问题:可以变得越来越宽 * 原因:timer并不是每次在鼠标经过每一个区域时为null * 解决办法:在前面的for循环中加上aLi[i].timer = null;这样每次执行前都是null开始 */ function startMove(obj,iTarget){//因为li有多个,这里需要再传一个参数obj //var aLi = document.getElementsByTagName('li'); clearInterval(obj.timer); obj.timer = setInterval(function(){ var speed = (iTarget - obj.offsetWidth)/10; speed = speed>0?Math.ceil(speed):Math.floor(speed); if(iTarget == obj.offsetWidth){ clearInterval(obj.timer); } else{ obj.style.width = obj.offsetWidth+speed+'px'; //是obj 不是 aLi } },30) } </script> </head> <body> <ul> <li></li> <li></li> <li></li> </ul> </body> </html>
【多物体透明度动画】
有了上面的例子,我们就能很容易的写出多物体透明度动画的代码,代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>多物体透明度动画</title> <style type="text/css"> body,div{ margin: 0px; padding: 0px; } div{ width: 200px; height: 200px; background: red; margin: 10px; float: left; filter:alpha(opacity:30); opacity:0.3; } </style> <script type="text/javascript"> window.onload = function(){ var oDiv = document.getElementsByTagName('div'); for(var i=0;i<oDiv.length;i++){ oDiv[i].timer = null; oDiv[i].alpha = 30; oDiv[i].onmouseover = function(){ startMove(this,100); } oDiv[i].onmouseout = function(){ startMove(this,30); } } } //var alpha = 30; function startMove(obj,iTarget){ clearInterval(obj.timer); obj.timer = setInterval(function(){ var speed = 0; if(iTarget > obj.alpha){ speed = 10; } else{ speed = -10; } if(iTarget == obj.alpha){ clearInterval(obj.timer); } else{ obj.alpha +=speed; obj.style.filter = 'obj.alpha(opacity:'+obj.alpha+')'; obj.style.opacity = obj.alpha/100; } },30) } </script> </head> <body> <div id="div1"></div> <div id="div2"></div> <div id="div3"></div> <div id="div4"></div> </body> </html>
和之前的timer一样,alpha = 30;也需要写在for循环的后面。
到这里,简单的动画效果就告一段落了,慢慢的一步一步的去修改去尝试就会有新的发现。