业务需求:
案例分析:
① 利用动画函数做动画效果
② 原先筋斗云的起始位置是0
③ 鼠标经过某个小li, 把当前小li 的 offsetLeft 位置 做为目标值即可
④ 鼠标离开某个小li, 就把目标值设为 0
⑤ 如果点击了某个小li, 就把 li 当前的位置存储起来,做为筋斗云的起始位置。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>案例:筋头云案例</title> <style> * { margin: 0; padding: 0; } ul { list-style: none; } body { background-color: black; } .c-nav { position: relative; width: 900px; height: 42px; background: #fff url(images/rss.png) no-repeat right center; margin: 100px auto; border-radius: 5px; } .c-nav ul { position: absolute; } .c-nav li { float: left; width: 83px; text-align: center; line-height: 42px; } .c-nav li a { display: inline-block; height: 42px; color: #333; text-decoration: none; } .c-nav li a:hover { color: white; } .c-nav li.current a { color: #0dff1d; } .cloud { position: absolute; left: 0; top: 0; width: 83px; height: 42px; background: url(images/cloud.gif) no-repeat; } </style> <script src="animate.js"></script> <script> window.addEventListener('load', function () { // 1.获取元素 var cloud = document.querySelector('.cloud'); var c_nav = document.querySelector('.c-nav'); var lis = c_nav.querySelectorAll('li'); // 2.给所有的小li绑定事件 // 这个current 做为筋斗云的起始位置 var current = 0; for (var i = 0; i < lis.length; i++) { // (1) 鼠标经过把当前小li 的位置做为目标值 lis[i].addEventListener('mouseenter', function () { animate(cloud, this.offsetLeft); }); // (2) 鼠标离开就回到起始的位置 lis[i].addEventListener('mouseleave', function () { animate(cloud, current); }); // (3) 当我们鼠标点击,就把当前位置做为目标值 lis[i].addEventListener('click', function () { current = this.offsetLeft; // 干掉所有人 其余的li清除 class 这个类 for (var j = 0; j < lis.length; j++) { lis[j].className = ''; } // 留下我自己 this.className = 'current'; }); } }); </script> </head> <body> <div id="c_nav" class="c-nav"> <span class="cloud"></span> <ul> <li class="current"><a href="#">首页新闻</a></li> <li><a href="#">师资力量</a></li> <li><a href="#">活动策划</a></li> <li><a href="#">企业文化</a></li> <li><a href="#">招聘信息</a></li> <li><a href="#">公司简介</a></li> <li><a href="#">我是佩奇</a></li> <li><a href="#">啥是佩奇</a></li> </ul> </div> </body> </html>
动画函数:
// 缓动动画函数封装obj目标对象 target 目标位置 // 思路: // 1. 让盒子每次移动的距离慢慢变小, 速度就会慢慢落下来。 // 2. 核心算法:(目标值 - 现在的位置) / 10 做为每次移动的距离 步长 // 3. 停止的条件是: 让当前盒子位置等于目标位置就停止定时器 function animate(obj, target, callback) { // console.log(callback); callback = function() {}; 调用的时候 callback() // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function () { // 步长值写到定时器的里面 // 把我们的步长值改为整数 不要出现小数的问题 var step = (target - obj.offsetLeft) / 10; // 判断步长是正值还是负值 // 如果是正值,则步长往大了的取整(向上取整 Math.ceil() ,如8.1 取到9) // 如果是负值,则步长往小了的取整(向下取整 Math,floor() ,如-8.1 取到-8) step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); // 回调函数写到定时器结束里面 // if (callback) { // 调用函数 // callback(); // } callback && callback(); } // 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); }