视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
js----反弹动画实现
2020-11-27 20:16:24 责编:小采
文档
代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <style>#box{
 width:200px;
 height:200px;
 position: absolute;
 top:0;
 left:200px;
 background:lightblue;
 }
 .btn{
 position:absolute;
 top:200px;
 left:100px;
 height:50px;
 }
 .btn input{
 display:inline-block;
 margin-left:50px;
 outline: none;
 width:100px;
 height:50px;
 border:1px solid green;
 cursor:pointer;
 }</style>
</head>
<body>
 <div id='box'></div>
 <div class='btn'>
 <input type="button" value='向左' id='btnLeft'>
 <input type="button" value='向右' id='btnRight'>
 </div>
 <script>var oBox = document.getElementById("box");var minLeft = 0;var maxLeft = utils.win('clientWidth')-oBox.offsetWidth;var step = 5;var timer = null;function move(target){//target:告诉我要运动的目标位置 window.clearTimeout(timer);var curLeft = utils.css(oBox,"left");if(curLeft<target){//向右走if(curLeft+step>target){//边界utils.css(oBox,"left",target);return;
 }
 curLeft+=step;
 utils.css(oBox,"left",curLeft)
 }else if(curLeft>target){//向左走if(curLeft-step<target){//边界utils.css(oBox,"left",target);return;
 }
 curLeft-=step;
 utils.css(oBox,"left",curLeft)
 }else{//不需要运动return;
 }// timer = window.setTimeout(move,10)//这里有一个问题,点击按钮第一次target的值是有的,但是第二次通过setTimeout执行的时候没有给target进行传值。是undefinedtimer = window.setTimeout(function(){
 move(target);
 },10)//这样使用匿名函数包裹一下,就解决了上面的问题,但是这样写性能不好,因为每一次到达时间的时候,都需要执行一次匿名函数(形成一个私有的作用域),在匿名函数中再执行move,但是move中需要用到的数据值在第一次执行的move方法中,需要把匿名函数形成的这个私有的作用域作为跳板找到之前的,这样就导致了匿名函数形成的这个私有的作用域不能销毁 }
 document.getElementById('btnLeft').onclick = function(){
 move(minLeft)
 }
 document.getElementById('btnRight').onclick = function(){
 move(maxLeft)
 } </script>
</body>
</html>

为了解决上面性能不好的问题,下面是一个优化后的代码:里面在使用一个函数包裹,这样就只有move函数创建的一个私有作用域没有销毁,等到_move执行完毕,move就自然会进行销毁。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Document</title>
 <style>#box{
 width:200px;
 height:200px;
 position: absolute;
 top:0;
 left:200px;
 background:lightblue;
 }
 .btn{
 position:absolute;
 top:200px;
 left:100px;
 height:50px;
 }
 .btn input{
 display:inline-block;
 margin-left:50px;
 outline: none;
 width:100px;
 height:50px;
 border:1px solid green;
 cursor:pointer;
 }</style>
</head>
<body>
 <div id='box'></div>
 <div class='btn'>
 <input type="button" value='向左' id='btnLeft'>
 <input type="button" value='向右' id='btnRight'>
 </div>
 <script>var oBox = document.getElementById("box");var minLeft = 0;var maxLeft = utils.win('clientWidth')-oBox.offsetWidth;var step = 5;var timer = null;function move(target){//target:告诉我要运动的目标位置 _move();function _move(){
 window.clearTimeout(timer);var curLeft = utils.css(oBox,"left");if(curLeft<target){//向右走if(curLeft+step>target){//边界utils.css(oBox,"left",target);return;
 }
 curLeft+=step;
 utils.css(oBox,"left",curLeft)
 }else if(curLeft>target){//向左走if(curLeft-step<target){//边界utils.css(oBox,"left",target);return;
 }
 curLeft-=step;
 utils.css(oBox,"left",curLeft)
 }else{//不需要运动return;
 }

 timer = window.setTimeout(_move,10);
 }
 
 }
 document.getElementById('btnLeft').onclick = function(){
 move(minLeft)
 }
 document.getElementById('btnRight').onclick = function(){
 move(maxLeft)
 } </script>
</body>
</html>

注意:为了让当前的元素在同一时间只运行一个动画(下一个动画开始的时候首先把上一个动画的定时器清除掉):保证当前元素所有动画接收定时器返回值的那个变量需要共享,有两种方式:1、全局接收(例如上面的代码 var timer = null)2、给元素增加自定义属性(如下图所示)

总结:通过以上可以得出动画优化的四条规则:

  1、边界判断加步长

  2、清除没有用的定时器

  3、在外层函数需要传参的时候,可以在里面在嵌套一层函数,避免作用域的累积。

  4、把定时器的返回值存储在元素的自定义属性上,防止全局变量冲突和同一时间多个动画执行

下载本文
显示全文
专题