【JavaScript】缓动动画、网页轮播图

    科技2022-07-13  127

    缓动动画

    动画函数封装1.1 动画实现原理 缓动动画1.1 缓动效果原理1.2 动画函数多个目标值之间移动1.3 动画函数添加回调函数1.4 动画函数封装到单独JS文件里面案例:京东侧边栏滑动案例:网页轮播图1.5 节流阀案例:筋斗云

    动画函数封装

    1.1 动画实现原理

    核心原理:通过定时器setInterval0 不断移动盒子位置。

    实现步骤:

    1.获得盒子当前位置

    2.让盒子在当前位置加上1个移动距离

    3.利用定时器不断重复这个操作

    4.加一个结束定时器的条件

    5.注意此元素需要添加定位,才能使用element.style.left

    // var obj = {};

    // obj.name = 'xxx';

    // 简单动画函数封装obj目标对象 target 目标位置

    // 给不同的元素指定了不同的定时器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { position: absolute; left: 0; width: 100px; height: 100px; background-color: pink; } span { position: absolute; left: 0; top: 200px; display: block; width: 150px; height: 150px; background-color: purple; } </style> </head> <body> <button>点击夏雨荷才走</button> <div></div> <span>夏雨荷</span> <script> var div = document.querySelector('div'); var span = document.querySelector('span'); var btn = document.querySelector('button'); // var obj = {}; // obj.name = 'xxx'; // 简单动画函数封装obj目标对象 target 目标位置 // 给不同的元素指定了不同的定时器 //1.封装函数 function move(obj, target) { // 2.1清除多次点击后的定时器,保留最新的那一次 clearInterval(obj.timer); // 1.1设置定时器 obj.timer = setInterval(function () { // 1.2清除定时器 if (obj.offsetLeft >= target) { clearInterval(obj.timer); } // 1.3设置运动距离 obj.style.left = obj.offsetLeft + 1 + 'px'; }, 30); } //2.调用函数 move(div, 300); btn.addEventListener('click', function () { move(span, 200); }) // 当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器 // 解决方案就是 让我们元素只有一个定时器执行 // 先清除以前的定时器,只保留当前的一个定时器执行 </script> </body> </html>

    缓动动画

    1.1 缓动效果原理

    缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来

    思路:

    1.让盒子每次移动的距离慢慢变小 ,速度就会慢慢落下来

    2.核心算法: (目标值-现在的位置) /10 做为每次移动的距离 步长

    3.停止的条件是: 让当前盒子位置等于目标位置就停止定时器

    4.注意步长值需要取整

    1.2 动画函数多个目标值之间移动

    可以让动画函数从800移动到500

    当我们点击按钮时候,判断步长是正值还是负值:如果是正值,则步长往大的取整,如果是负值,则步长向小的取整

    <script> // 把我们步长值改为整数 不要出现小数的问题 // var step = Math.ceil((target - obj.offsetLeft) / 10); var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); </script>

    1.3 动画函数添加回调函数

    回调函数原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数,这个过程就叫做回调。

    回调函数写的位置:定时器结束的位置

    1.4 动画函数封装到单独JS文件里面

    因为以后经常使用这个动画函数,可以单独封装到一个Js文件里面,使用的时候引用这个Js文件即可。

    animate.js文件

    function animate(obj, target, callback) { // console.log(callback); callback = function() {} 调用的时候 callback() // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步长值写到定时器的里面 // 把我们步长值改为整数 不要出现小数的问题 // var step = Math.ceil((target - obj.offsetLeft) / 10); var step = (target - obj.offsetLeft) / 10; 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); }

    案例:京东侧边栏滑动

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .sliderbar { position: fixed; right: 0; bottom: 100px; width: 40px; height: 40px; text-align: center; line-height: 40px; cursor: pointer; color: #fff; } .con { position: absolute; left: 0; top: 0; width: 200px; height: 40px; background-color: purple; z-index: -1; } </style> <script src="animate.js"></script> </head> <body> <div class="sliderbar"> <span></span> <div class="con">问题反馈</div> </div> <script> // 1. 获取元素 var sliderbar = document.querySelector('.sliderbar'); var con = document.querySelector('.con'); // 当我们鼠标经过 sliderbar 就会让 con这个盒子滑动到左侧 // 当我们鼠标离开 sliderbar 就会让 con这个盒子滑动到右侧 sliderbar.addEventListener('mouseenter', function() { // animate(obj, target, callback); animate(con, -160, function() { // 当我们动画执行完毕,就把 ← 改为 → sliderbar.children[0].innerHTML = '→'; }); }) sliderbar.addEventListener('mouseleave', function() { // animate(obj, target, callback); animate(con, 0, function() { sliderbar.children[0].innerHTML = '←'; }); }) </script> </body> </html>

    案例:网页轮播图

    功能需求:

    1.鼠标经过轮播图模块 ,左右按钮显示,离开隐藏左右按钮。

    2.动态生成小圆圈

    ②核心思路:小圆圈的个数要跟图片张数一致

    ③所以首先先得到ul里面图片的张数(图片放入i里面,所以就是li的个数)

    ④利用循环动态生成小圆圈(这个小圆圈要放入ol里面)

    ⑤创建节点createElement(‘li’)

    ⑥插入节点ol.appendChild(li)

    3.点击右侧按钮一次,图片往左播放一张,以此类推,左侧按钮同理。

    4.图片播放的同时,下面小圆圈模块跟随一起变化。

    5.点击小圆圈 ,可以播放相应图片。

    6.鼠标不经过轮播图 ,轮播图也会自动播放图片。

    7.鼠标经过,轮播图模块,自动播放停止。

    至于为何有缝隙有待研究 html代码:

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="animate.js"></script> <script src="4.轮播.js"></script> <style> * { margin: 0; padding: 0; } .focus { position: relative; margin: 20px auto; width: 724px; height: 455px; background-color: purple; overflow: hidden; } .focus ul { position: absolute; top: 0; left: 0; width: 600%; } .focus ul li { float: left; list-style: none; } .arrow-l, .arrow-r { display: none; position: absolute; top: 50%; margin-top: -20px; width: 24px; height: 40px; background: rgba(0, 0, 0, .3); text-align: center; line-height: 40px; color: #fff; z-index: 2; text-decoration: none; } .arrow-r { right: 0; } .circle { position: absolute; bottom: 10px; left: 50px; z-index: 1; list-style: none; } .circle li { float: left; width: 8px; height: 8px; /*background-color: #fff;*/ border: 2px solid rgba(255, 255, 255, 0.5); margin: 0 3px; border-radius: 50%; /*鼠标经过显示小手*/ cursor: pointer; } .current { background-color: #fff; } </style> </head> <body> <div class="focus fl"> <!-- 左侧按钮 --> <a href="javascript:;" class="arrow-l"><</a> <!-- 右侧按钮 --> <a href="javascript:;" class="arrow-r"> ></a> <!-- 核心的滚动区域 --> <ul> <li> <a href="#"><img src="imag/focus.jpg" alt=""></a> </li> <li> <a href="#"><img src="imag/focus1.jpg" alt=""></a> </li> <li> <a href="#"><img src="imag/focus2.jpg" alt=""></a> </li> <li> <a href="#"><img src="imag/focus3.jpg" alt=""></a> </li> </ul> <!-- 小圆圈 --> <ol class="circle"> </ol> </div> </body> </html>

    js代码:

    window.addEventListener('load', function () { // 1.获取元素 var arrow_l = document.querySelector('.arrow-l'); var arrow_r = document.querySelector('.arrow-r'); var focus = document.querySelector('.focus'); // 2.鼠标经过focus 就显示隐藏左右按钮 focus.addEventListener('mouseenter', function () { arrow_l.style.display = 'block'; arrow_r.style.display = 'block'; clearInterval(timer); timer = null; // 清除定时器变量 }) focus.addEventListener('mouseleave', function () { arrow_l.style.display = 'none'; arrow_r.style.display = 'none'; timer = setInterval(function () { //手动调用点击事件 arrow_r.click(); }, 2000); }) // 3.动态生成小圆点 var ul = focus.querySelector('ul'); var ol = focus.querySelector('.circle'); for (var i = 0; i < ul.children.length; i++) { var li = document.createElement('li'); ol.appendChild(li); // 5.1记录当前图片的索引 li.setAttribute('index', i); // 4.绑定事件,排他思想 li.onclick = function () { // 干掉所有 for (var i = 0; i < ol.children.length; i++) { ol.children[i].className = ''; } this.className = 'current'; // 5.点击小圆点移动图片 // 当我们点击了某个小li 就拿到当前小li 的索引号 var index = this.getAttribute('index'); var focusWidth = focus.offsetWidth; animate(ul, -index * focusWidth); //8.2 当我们点击了某个小li 就要把这个li 的索引号给 num num = index; // 8.3当我们点击了某个小li 就要把这个li 的索引号给 circle circle = index; } } // 4.1第一个圆点默认current ol.children[0].className = 'current'; // 6.克隆第一张图在末尾 var first = ul.children[0].cloneNode(true); ul.appendChild(first); // 7.点击右侧按钮,图片滚动一张 var num = 0; // 8.1 var circle = 0; arrow_r.addEventListener('click', function () { if (num == ul.children.length - 1) { num = 0; ul.style.left = 0; } num++; var focusWidth = focus.offsetWidth; animate(ul, -num * focusWidth, function () { flag = true; }); // 8. 点击右侧按钮,小圆圈跟随一起变化 可以再声明一个变量控制小圆圈的播放 circle++; // 如果circle == 4 说明走到最后我们克隆的这张图片了 我们就复原 if (circle == ol.children.length) { circle = 0; } circleChange(); }) // 9. 左侧按钮做法 arrow_l.addEventListener('click', function () { // 12 if (num == 0) { num = ul.children.length - 1; ul.style.left = -num * focusWidth + 'px'; } num--; var focusWidth = focus.offsetWidth; animate(ul, -num * focusWidth); circle--; if (circle < 0) { circle = ol.children.length - 1; } circleChange(); }) function circleChange() { // 清除其余的小圆点样式 for (var i = 0; i < ol.children.length; i++) { ol.children[i].className = ''; } //留下当前的样式 ol.children[circle].className = 'current'; } // 10. 自动播放轮播图 var timer = setInterval(function () { //手动调用点击事件 arrow_r.click(); }, 2000); })

    1.5 节流阀

    防止轮播图按钮连续点击造成播放过快。

    节流阀目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发。

    核心实现思路:利用回调函数,添加一个变量来控制 ,锁住函数和解锁函数。

    开始设置一个变量var flag= true;

    If (flag) {flag= false; do something}关闭水龙头

    利用回调函数动画执行完毕, flag=true 打开水龙头

    案例:筋斗云

    鼠标经过某个小li ,筋斗云跟这到当前小i位置

    鼠标离开这个小li,筋斗云复原为原来的位置

    鼠标点击了某个小li ,筋斗云就会留在点击这个小i的位置

    js代码:

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0 } ul { list-style: none; } body { background-color: black; } .c-nav { width: 900px; height: 42px; background: #fff url(images/rss.png) no-repeat right center; margin: 100px auto; border-radius: 5px; position: relative; } .c-nav ul { position: absolute; } .c-nav li { float: left; width: 83px; text-align: center; line-height: 42px; } .c-nav li a { color: #333; text-decoration: none; display: inline-block; height: 42px; } .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; }); } }) </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>
    Processed: 0.013, SQL: 8