1.平滑运动
-
需求:点击起飞 盒子开始移动 移动到1000px 盒子停止
<body> <button>起飞</button> <div></div> <script> /* 需求:点击起飞按钮 红色盒子开始移动 移动到1000px的位置开始停止 */ var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] //添加点击事件 btn.onclick = function () { var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(oDiv, "left")) + 10; if(current==1000){ // 清除定时器 clearInterval(timer) } oDiv.style.left = current + "px"; }, 50) } </script>
2.缓冲动画基础功能
-
需求:目标值是500和目标值是1000 所花费的时间是一样的
<body> <button>起飞</button> <div></div> <script> /* 需求:目标值是500和目标值是1000 所花费的时间是一样的 速速 = 路程 / 时间 */ var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] //添加点击事件 btn.onclick = function () { var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(oDiv, "left")); var speed = (500 - current) / 10;// speed 速度/步长 console.log(current);//永远达不到目标值 if (current == 500) { // 清除定时器 clearInterval(timer) } oDiv.style.left = current + speed + "px"; }, 50) } </script>
-
问题1:永远到不了目标值
-
原因:当current是491的时候 speed=0.9 left值=parseInt(491.9px) =491 所以current的值始终在491
-
解决方法:让speed向上取整 Math.ceil
-
<body> <button>起飞</button> <div></div> <p></p> <script> /* 问题1:永远达不到目标值 原因:当current是491的时候 speed=0.9 left值=parseInt(491.9px) =491 所以current的值始终在491 解决方法:让speed向上取整 Math.ceil */ var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] //添加点击事件 btn.onclick = function () { var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(oDiv, "left")); var speed = (500 - current) / 10; // speed 速度/步长 speed = Math.ceil(speed); console.log(speed); if (current == 500) { // 清除定时器 clearInterval(timer) } oDiv.style.left = current + speed + "px"; }, 50) } </script> </body>
3缓冲动画来回运动
-
需求:从left值是1000的位置 缓冲到500的位置
-
问题2:往回运动的时候 永远无法达到目标值
-
分析:current是509的时候 speed的值是-0.9 Math.ceil之后就成了-0 speed的值最终是0 left值还是509 导致目标值永远都是509
-
解决:让speed向下取整 Math.floor
-
<body> <button>起飞</button> <div></div> <p></p> <script> var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] /* 问题2:往回运动的时候 永远无法达到目标值 分析:current是509的时候 speed的值是-0.9 Math.ceil之后就成了-0 speed的值最终是0 left值还是509 导致目标值永远都是509 解决:让speed向下取整 Math.floor */ //添加点击事件 btn.onclick = function () { var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(oDiv, "left")); var speed = (500 - current) / 10; // speed 速度/步长 speed = Math.floor(speed); console.log(current); if (current == 500) { // 清除定时器 clearInterval(timer) } oDiv.style.left = current + speed + "px"; }, 50) } </script> </body>
-
来回运动speed值的问题
-
0-500 speed的值正数 Math.ceil
-
1000-500 speed的值是负数 Math.floor
-
<body> <button>起飞</button> <div></div> <p></p> <script> var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] /* speed值的问题 0-500 speed的值正数 Math.ceil 1000-500 speed的值是负数 Math.floor */ //添加点击事件 btn.onclick = function () { var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(oDiv, "left")); var speed = (500 - current) / 10; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == 500) { // 清除定时器 clearInterval(timer) } oDiv.style.left = current + speed + "px"; }, 50) } </script> </body>
4.来回运动函数封装
<body> <button>起飞</button> <div></div> <p></p> <script> var btn = document.getElementsByTagName("button")[0]; var oDiv = document.getElementsByTagName("div")[0] /* speed值的问题 0-500 speed的值正数 Math.ceil 1000-500 speed的值是负数 Math.floor */ //添加点击事件 btn.onclick = function () { buffMove(oDiv, "left", 500, 20); } function buffMove(elem, attr, target, time) { /* elem 缓冲的元素 attr 需要缓冲的样式 target是目标值 time是缓冲时间 */ var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(elem, attr)); var speed = (target - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == target) { // 清除定时器 clearInterval(timer) } elem.style[attr] = current + speed + "px"; }, 50) } </script> </body>
5.透明度缓冲
-
问题3:缓冲透明度从1到0 没有缓冲动画
-
分析:current是1的时候 speed的值-0.1 用Math.floor取整之后变成-1 opacity的值是0
-
解决:是因为透明度的值太小了 将透明度的值放大n倍 放大100倍
-
<body> <div></div> <script> /* 问题3:缓冲透明度从1到0 没有缓冲动画 分析:current是1的时候 speed的值-0.1 用Math.floor取整之后变成-1 opacity的值是0 解决:是因为透明度的值太小了 将透明度的值放大n倍 放大100倍 */ var oDiv = document.getElementsByTagName("div")[0]; oDiv.onclick = function () { // 更改透明度 1-0 buffMove(oDiv, "opacity", 0.2, 10) } function buffMove(elem, attr, target, time) { /* elem 缓冲的元素 attr 需要缓冲的样式 target是目标值 time是缓冲时间 */ target = target * 100 var timer = setInterval(function () { //在当前left值的基础上+10 var current = parseInt(getStyle(elem, attr) * 100); var speed = (target - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == target) { // 清除定时器 clearInterval(timer) } // 其他属性 // elem.style[attr] = current + speed + "px"; // 透明度opacity elem.style[attr] = (current + speed) / 100; }, 50) } </script> </body>
6.缓冲任意属性
<body> <div></div> <script> var oDiv = document.getElementsByTagName("div")[0]; oDiv.onclick = function () { // buffMove(oDiv,"width",500,10) buffMove(oDiv,"opacity",0.2,10) } function buffMove(elem, attr, target, time) { /* elem 缓冲的元素 attr 需要缓冲的样式 target是目标值 time是缓冲时间 */ var timer = setInterval(function () { //在当前left值的基础上+10 if (attr == 'opacity') { // 透明度属性 var current = parseInt(getStyle(elem, attr) * 100); // opacity target的取值范围是0-1 才需要*100 其他属性大于1 不需要*100 target = target > 1 ? target : target * 100 } else {//其他属性 var current = parseInt(getStyle(elem, attr)); } var speed = (target - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == target) { // 清除定时器 clearInterval(timer) } if (attr == "opacity") { // 透明度opacity elem.style[attr] = (current + speed) / 100; } else { // 其他属性 elem.style[attr] = current + speed + "px"; } }, 50) } </script> </body>
7.抽屉式运动
-
问题1:在移入事件的缓冲动画没有完成之前就移除 会造成盒子抽搐
-
分析:是因为定时器累计的问题
-
解决:在定义一个新的定时器之前就清除原先的定时器 确保只有一个定时器
-
-
问题2:同时运动多个盒子 盒子无法达到目标值
-
分析:多个盒子都是调用buffMove函数 一进入这个函数就将之前的定时器清除掉了 共用了一个定时器的缘故
-
解决:给每个盒子都单独定义一个timer,将每个盒子的定时器id都存储到元素的自定义属性timer上
-
<body> <div>1</div> <div>2</div> <script> var oDiv = document.getElementsByTagName("div"); oDiv[0].onmouseover = function(){ // 200px-500px buffMove(oDiv[0],"width",500,10) } oDiv[0].onmouseout = function(){ // 500px-200px buffMove(oDiv[0],"width",200,10) } oDiv[1].onmouseover = function(){ //200-500px; buffMove(oDiv[1],"width",500,10) } oDiv[1].onmouseout = function(){ //500px-200px buffMove(oDiv[1],"width",200,10) } // var timer; function buffMove(elem, attr, target, time) { /* elem 缓冲的元素 attr 需要缓冲的样式 target是目标值 time是缓冲时间 */ clearInterval(elem.timer); //将每个盒子的定时器id都存储到元素的自定义属性timer上 elem.timer = setInterval(function () { //在当前left值的基础上+10 if (attr == 'opacity') { // 透明度属性 var current = parseInt(getStyle(elem, attr) * 100); // opacity target的取值范围是0-1 才需要*100 其他属性大于1 不需要*100 target = target > 1 ? target : target * 100 } else {//其他属性 var current = parseInt(getStyle(elem, attr)); } var speed = (target - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == target) { // 清除定时器 clearInterval(elem.timer) } if (attr == "opacity") { // 透明度opacity elem.style[attr] = (current + speed) / 100; } else { // 其他属性 elem.style[attr] = current + speed + "px"; } }, 50) } </script> </body>
8.多属性运动
-
问题1:运动多个属性的时候,无法多次调用buffMove函数,因为后者会覆盖前者
-
解决:buffMove只能调用一次 可以每次传值的时候一个对象,对象存储格式为{"width":500,"height":500} {"样式名":目标值}
-
<script> var oDiv = document.getElementsByTagName("div")[0]; oDiv.onclick = function () { // 想同时运动多个属性 buffMove只能调用一次 可以每次传值的时候传多个 参数{"width":500,"height":500} buffMove(oDiv, { "width": 500, "height": 500 }, 10) } //需求:同时运动width和height function buffMove(elem, attrObj, time) { /* elem 缓冲的元素 attrObj同时运动属性的对象{样式名:目标值}*/ clearInterval(elem.timer); elem.timer = setInterval(function () { // name变量中存储的是width height 也就是要缓冲的样式 // 目标值attrObj[name] 原先的目标值target需要替换成attrObj[name] for (var name in attrObj) { //在当前left值的基础上+10 if (name == "opacity") { // name是opacity var current = parseInt(getStyle(elem, name) * 100); // target的值是0-1 更改的是透明度,透明度需要*100 target>1 其他属性的值 不需要*100 attrObj[name] = attrObj[name] > 1 ? attrObj[name] : attrObj[name] * 100 // } else { // name是其他属性 var current = parseInt(getStyle(elem, name)); } var speed = (attrObj[name] - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) console.log(current); if (current == attrObj[name]) { // 清除定时器 clearInterval(elem.timer) } if (name == "opacity") { // 透明度opacity elem.style[name] = (current + speed) / 100; } else { // 其他属性 elem.style[name] = current + speed + "px"; } } }, 50) } </script>
-
问题2:如果多个属性的目标值不一致,个别属性无法到达目标点
-
分析:如果某一个属性达到目标值 就会进到if(current==attrObj[name]) 就会清除定时器 导致剩余属性无法继续执行
-
解决:
1.假设所有属性都达到目标点再去清除定时器 var tag = true
2.验证你假设的情况 一个一个属性的去验证
3.验证之后你会得到一个结论 你的假设要么成立 要么不成立 如果成立清除定时器
-
<body> <div></div> <script> /* 问题1:如果多个属性目标值不一致的话 个别属性无法达到目标点 分析:如果某一个属性达到目标值 就会进到if(current==attrObj[name]) 就会清除定时器 导致剩余属性无法继续执行 解决: 1.假设所有属性都达到目标点再去清除定时器 var tag = true 2.验证你假设的情况 一个一个属性的去验证 3.验证之后你会得到一个结论 你的假设要么成立 要么不成立 如果成立清除定时器 */ var oDiv = document.getElementsByTagName("div")[0]; oDiv.onclick = function () { buffMove(oDiv, { "width": 1, "height": 1000 }, 10) } function buffMove(elem, attrObj, time) { /* elem 缓冲的元素 attrObj同时运动属性的对象{样式名:目标值}*/ clearInterval(elem.timer); elem.timer = setInterval(function () { var tag = true;// 初始值定义为true 假设所有的属性都达到了目标点 for (var name in attrObj) { //在当前left值的基础上+10 if (name == "opacity") { // name是opacity var current = parseInt(getStyle(elem, name) * 100); // target的值是0-1 更改的是透明度,透明度需要*100 target>1 其他属性的值 不需要*100 attrObj[name] = attrObj[name] > 1 ? attrObj[name] : attrObj[name] * 100 // } else { // name是其他属性 var current = parseInt(getStyle(elem, name)); } var speed = (attrObj[name] - current) / time; // speed 速度/步长 speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed) //2.去验证假设的情况 if(current!=attrObj[name]){ tag = false } if (name == "opacity") { // 透明度opacity elem.style[name] = (current + speed) / 100; } else { // 其他属性 elem.style[name] = current + speed + "px"; } } // 3.判断结论是否成立 if(tag){ clearInterval(elem.timer) } }, 50) } </script> </body>