动画实现原理
核心原理:通过定时器setInterval()不断移动盒子位置
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意此元素需要添加定位,才能使用element.style.left
<script> // 动画原理 // 1. 获得盒子当前位置 // 2. 让盒子在当前位置加上1个移动距离 // 3. 利用定时器不断重复这个操作 // 4. 加一个结束定时器的条件 // 5. 注意此元素需要添加定位, 才能使用element.style.left var div = document.querySelector('div'); var timer = setInterval(function() { if (div.offsetLeft >= 400) { // 停止动画 本质是停止定时器 clearInterval(timer); } div.style.left = div.offsetLeft + 1 + 'px'; }, 30); </script>结果演示
动画函数简单封装
<script> function animate(obj,target){ //当不断调用一个元素的定时器的时候,元素的速度会越来愈快,因为开启了太多的定时器, //所以要让元素只有一个定时器执行, //即先清除以前的定时器,只保留当前的一个定时器执行。 //clearInterval(obj.timer); //给不同的元素指定了不同的定时器obj.timer obj.timer = setInterval(function () { if (obj.offsetLeft >= target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); } obj.style.left = obj.offsetLeft + 1 + 'px'; }, 30); } var div = document.querySelector('div'); animate(div,300); </script>
缓动效果原理
缓动动画就是让元素运动速度有所变化,比如让速度慢慢停下来。
缓动动画公示
(目标位置-现在的位置)/10 作为每次移动的距离步长
<script> function animate(obj, target) { clearInterval(obj.timer); obj.timer = setInterval(function() { //把步长值改为整数(往上取整),不然小数会出现走不到目标位置的问题 var step = (target - obj.offsetLeft) / 10; //当步长大于0就往上取整(即取大值的整数),小于0就往下取整(即取小值的整负数) step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { clearInterval(obj.timer); } obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } var span = document.querySelector('span'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); btn500.addEventListener('click', function() { animate(span, 500); }) btn800.addEventListener('click', function() { animate(span, 800); }) </script>结果演示
动画函数添加回调函数
原理:函数可以作为一个参数。将这个函数作为参数传到另一个函数里面,当那个函数执行完之后(回调函数写在定时器结束的位置),再执行传进去的这个函数,这个过程称为回调。
<script> function animate(obj, target,callback) { clearInterval(obj.timer); obj.timer = setInterval(function() { //把步长值改为整数(往上取整),不然小数会出现走不到目标位置的问题 var step = (target - obj.offsetLeft) / 10; //当步长大于0就往上取整(即取大值的整数),小于0就往下取整(即取小值的整负数) step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { clearInterval(obj.timer); //回调函数下载定时器结束里面 //有回调函数才会执行 if(callback){ //调用函数 callback(); } } obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } var span = document.querySelector('span'); var btn500 = document.querySelector('.btn500'); var btn800 = document.querySelector('.btn800'); btn500.addEventListener('click', function() { animate(span, 500); }) btn800.addEventListener('click', function() { animate(span, 800,function(){ alert('我是回调函数'); }); }) </script>结果演示
常见网页特效案例
返回顶部
滚动窗口至文档中的特定位置
window.scroll(x,y)
分析
- 封装的动画函数要把所有的left值改为页面垂直
- 页面滚动了多少可以通过window.pageYOffset得到
- 最后是页面滚动,使用window.scroll(x,y)
<script> var btn=document.querySelector('button'); btn.addEventListener('click',function(){ animate(window,0) }) function animate(obj, target, callback) { clearInterval(obj.timer); obj.timer = setInterval(function () { //把步长值改为整数(往上取整),不然小数会出现走不到目标位置的问题 var step = (target - window.pageYOffset) / 10; //当步长大于0就往上取整(即取大值的整数),小于0就往下取整(即取小值的整负数) step = step > 0 ? Math.ceil(step) : Math.floor(step); if (window.pageYOffset == target) { clearInterval(obj.timer); if (callback) { callback(); } } window.scroll(0, window.pageYOffset+step); }, 15); } </script>结果演示
筋斗云
功能需求
- 鼠标经过某个小li,方块会跟到当前小li的位置
- 鼠标离开这个小li,方块会复原为原来的位置
- 鼠标点击了某个小li ,方块就会停在这个小li 的位置上
原理
- 原先方块的起始位置是0
- 鼠标经过某个小li,就把当前小li的位置(offsetLeft)作为目标值
- 鼠标离开后,就把目标值设为0
- 如果点击了某个小li,就把当前的位置储存起来,作为筋斗云的新起始位置
<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; }); } }) function animate(obj, target, callback) { // 先清除以前的定时器,只保留当前的一个定时器执行 clearInterval(obj.timer); obj.timer = setInterval(function () { // 步长值写到定时器的里面 // 把我们步长值改为整数 不要出现小数的问题 var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { // 停止动画 本质是停止定时器 clearInterval(obj.timer); callback && callback(); } // 把每次加1 这个步长值改为一个慢慢变小的值 步长公式:(目标值 - 现在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } </script>结果演示