一、指定步长的动画

  • JS 的动画:结合 JS 的定时器不断的操作元素的某些属性,实现动画效果。
  • 让盒子在水平方向上动起来,操作盒子的 left 值
  • 指定步长的动画原理:
    首先获取动画距离,使用动画终点 - 动画起点;然后使用一个定时器,每隔一定毫秒数获取当前元素的当前位置累加上步长,再把累加后的位置设置回去。在累加之前判断一下,当前位置是否已经到达了终点,如果到达终点清除定时器,并终止后面的操作。
  1. const {win, css} = window.utils;
  2. let box = document.getElementById('box');
  3. let step = 2; // 每次动画移动 2px
  4. // left 的最大值:屏幕宽度 - 元素的宽度
  5. let maxL = win('clientWidth') - css(box, 'width');
  6. let timer = setInterval(function () {
  7. let l = utils.css(box, 'left');
  8. // 结束动画条件
  9. if (l >= maxL) {
  10. clearInterval(timer);
  11. css(box, 'left', maxL);
  12. return;
  13. }
  14. l += 2;
  15. css(box, 'left', l)
  16. }, 16);

二、指定时长的动画

  • 指定时长的动画:要求元素在指定时间内从初始位置运动到某一指定位置。
  • 时间时固定的,路程是固定的,所以指定时间的动画关键在于求得速度,即每次定时器执行时元素改变的距离。
  1. const {win, css} = window.utils;
  2. let box = document.querySelector('#box');
  3. let s = 800; // 路程
  4. let t = 3000; // 3s
  5. let speed = s / t; // 速度
  6. let curT = 0; // 当前已经经过的时间
  7. let timer = setInterval(() => {
  8. curT += 16;
  9. // 结束动画时间
  10. if (curT >= t) {
  11. curT = t;
  12. clearInterval(timer);
  13. }
  14. let left = curT * speed;
  15. // 把计算出来的值设置回去
  16. css(box, 'left', left);
  17. }, 16);

三、回到顶部

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. * {
  8. margin: 0;
  9. padding: 0;
  10. }
  11. #box {
  12. height: 5000px;
  13. background: -webkit-linear-gradient(top left,red,blue,green,orange);
  14. }
  15. .btn {
  16. position: fixed;
  17. bottom: 50px;
  18. right: 50px;
  19. width: 80px;
  20. height: 80px;
  21. line-height: 80px;
  22. text-align: center;
  23. border-radius: 50%;
  24. cursor: pointer;
  25. user-select: none;
  26. background-color: #fff;
  27. color: #ddd;
  28. }
  29. </style>
  30. </head>
  31. <body>
  32. <div id="box"></div>
  33. <div class="btn" id="btn">上去</div>
  34. <!--<a href="#box">回到顶部</a>-->
  35. <!--锚点定位可以回到顶部-->
  36. <script src="js/utils.js"></script>
  37. <script src="js/5-回到顶部.js"></script>
  38. </body>
  39. </html>

方案1:直接将页面的 scrollTop 设为0

  1. const {css, win} = window.utils;
  2. let btn = document.getElementById('btn');
  3. // 1. 直接将页面的scrollTop设为0
  4. btn.onclick = function () {
  5. win('scrollTop', 0)
  6. };

方案2: 缓慢的回去-指定时间

  1. let isRun = false;
  2. btn.onclick = function () {
  3. if (isRun) return;
  4. // 2.1 固定时间上去 例如1s
  5. let top = win('scrollTop');
  6. let speed = top / 1000; // 速度 1000ms = 1s
  7. let time = 0; // 记录运动时长
  8. isRun = true;
  9. let timer = setInterval(() => {
  10. time += 50;
  11. if (time >= 1000) {
  12. time =1000;
  13. clearInterval(timer);
  14. isRun = false;
  15. }
  16. top = top - time * speed;
  17. win('scrollTop', top);
  18. }, 50)
  19. };

3. 缓慢回去-指定步长

  1. btn.onclick = function () {
  2. clearInterval(this.timer); // 防止动画累加,要清除动画
  3. this.timer = setInterval(() => {
  4. let top = win('scrollTop');
  5. top -= 20;
  6. if (top <= 0) {
  7. t = 0;
  8. clearInterval(this.timer);
  9. }
  10. win('scrollTop', top);
  11. }, 10)
  12. };

四、图片渐现

  • 用 js 实现让一张图片慢慢出现
  • HTML代码
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. <style>
  7. .img-con {
  8. width: 500px;
  9. height: 335px;
  10. background-color: #999999;
  11. }
  12. img {
  13. opacity: 0;
  14. }
  15. </style>
  16. </head>
  17. <body>
  18. <div class="img-con">
  19. <img src="leo.jpg" alt="">
  20. </div>
  21. <script src="js/utils.js"></script>
  22. <script src="js/3-图片渐现.js"></script>
  23. </body>
  24. </html>
  • JS 代码
  1. // 1. 导入工具方法
  2. const {css} = window.utils;
  3. // 2. 获取元素
  4. let img = document.querySelector('.img-con > img');
  5. // 3. 设定定时器启动动画
  6. let timer = setInterval(() => {
  7. // 3.1 获取当前元素的透明度
  8. let op = +css(img, 'opacity');
  9. // 3.2 给透明度累加,并判断累加后的值
  10. op += 0.01;
  11. if (op >= 1) {
  12. clearInterval(timer);
  13. op = 1;
  14. }
  15. // 3.3 把累加后的值设置回去
  16. css(img, 'opacity', op);
  17. }, 16);

五、匀速动画

  • 需求:让页面中的盒子在 2s 内从起始位置匀速运动到 left 是 800 的位置
  • 匀速运动中速度是一定的,时间时固定的,所以最为关键的是求出路程,然后再求出速度;
  1. const {css} = window.utils;
  2. let box = document.getElementById('box');
  3. // 过度时间
  4. let duration = 2000;
  5. // 目标值
  6. let target = 800;
  7. // 起始位置
  8. let begin = css(box, 'left');
  9. // 总移动距离
  10. let change = target - begin;
  11. // 记录当前时间
  12. let time = 0;
  13. let interval = 16;
  14. let timerId = setInterval(() => {
  15. time += 10;
  16. if (time >= duration) {
  17. css(box, 'left', target);
  18. clearInterval(timerId);
  19. return
  20. }
  21. let curLeft = change / duration * time + begin;
  22. css(box, 'left', curLeft)
  23. }, interval);
  • 匀速运动中某一时刻的位置计算
  1. function linear(curTime, begin, change, duration) {
  2. // 计算匀速运动时,元素某一时刻的位置
  3. return (change / duration) * curTime + begin;
  4. }

六、多方向的匀速动画

  • 让页面中的 div 在 2s 内运动到的 left 值是 850,top 值是 500 的位置;
  • 多方向的匀速动画即元素的多个 js 属性同时变化
  1. const {css} = window.utils;
  2. // 过度时间 2000
  3. let duration = 2000;
  4. // 目标值
  5. let targetLeft = 800;
  6. let targetTop = 500;
  7. // 获取起始位置
  8. let beginLeft = css(box, 'left');
  9. let beginTop = css(box, 'top');
  10. // 获取总路程
  11. let changeLeft = targetLeft - beginLeft;
  12. let changeTop = targetTop - beginTop;
  13. // 记录时间
  14. let time = 0;
  15. // 定时器执行间隔
  16. const interval = 16;
  17. let timerId = setInterval(() => {
  18. time += interval;
  19. // 动画结束条件判断
  20. if (time >= duration) {
  21. css(box, {
  22. left: targetLeft,
  23. top: targetTop
  24. });
  25. clearInterval(timerId);
  26. return;
  27. }
  28. // 计算当前时刻元素 left 和 top 的值
  29. let curLeft = linear(time, beginLeft, changeLeft, duration);
  30. let curTop = linear(time, beginTop, changeTop, duration);
  31. css(box, {
  32. left: curLeft,
  33. top: curTop
  34. })
  35. }, interval);
  36. function linear(curTime, begin, change, duration) {
  37. // 计算匀速运动时,元素某一时刻的位置
  38. return (change / duration) * curTime + begin;
  39. }