一、指定步长的动画
- JS 的动画:结合 JS 的定时器不断的操作元素的某些属性,实现动画效果。
- 让盒子在水平方向上动起来,操作盒子的 left 值
- 指定步长的动画原理:
首先获取动画距离,使用动画终点 - 动画起点;然后使用一个定时器,每隔一定毫秒数获取当前元素的当前位置累加上步长,再把累加后的位置设置回去。在累加之前判断一下,当前位置是否已经到达了终点,如果到达终点清除定时器,并终止后面的操作。
const {win, css} = window.utils;let box = document.getElementById('box');let step = 2; // 每次动画移动 2px// left 的最大值:屏幕宽度 - 元素的宽度let maxL = win('clientWidth') - css(box, 'width');let timer = setInterval(function () {let l = utils.css(box, 'left');// 结束动画条件if (l >= maxL) {clearInterval(timer);css(box, 'left', maxL);return;}l += 2;css(box, 'left', l)}, 16);
二、指定时长的动画
- 指定时长的动画:要求元素在指定时间内从初始位置运动到某一指定位置。
- 时间时固定的,路程是固定的,所以指定时间的动画关键在于求得速度,即每次定时器执行时元素改变的距离。
const {win, css} = window.utils;let box = document.querySelector('#box');let s = 800; // 路程let t = 3000; // 3slet speed = s / t; // 速度let curT = 0; // 当前已经经过的时间let timer = setInterval(() => {curT += 16;// 结束动画时间if (curT >= t) {curT = t;clearInterval(timer);}let left = curT * speed;// 把计算出来的值设置回去css(box, 'left', left);}, 16);
三、回到顶部
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><style>* {margin: 0;padding: 0;}#box {height: 5000px;background: -webkit-linear-gradient(top left,red,blue,green,orange);}.btn {position: fixed;bottom: 50px;right: 50px;width: 80px;height: 80px;line-height: 80px;text-align: center;border-radius: 50%;cursor: pointer;user-select: none;background-color: #fff;color: #ddd;}</style></head><body><div id="box"></div><div class="btn" id="btn">上去</div><!--<a href="#box">回到顶部</a>--><!--锚点定位可以回到顶部--><script src="js/utils.js"></script><script src="js/5-回到顶部.js"></script></body></html>
方案1:直接将页面的 scrollTop 设为0
const {css, win} = window.utils;let btn = document.getElementById('btn');// 1. 直接将页面的scrollTop设为0btn.onclick = function () {win('scrollTop', 0)};
方案2: 缓慢的回去-指定时间
let isRun = false;btn.onclick = function () {if (isRun) return;// 2.1 固定时间上去 例如1slet top = win('scrollTop');let speed = top / 1000; // 速度 1000ms = 1slet time = 0; // 记录运动时长isRun = true;let timer = setInterval(() => {time += 50;if (time >= 1000) {time =1000;clearInterval(timer);isRun = false;}top = top - time * speed;win('scrollTop', top);}, 50)};
3. 缓慢回去-指定步长
btn.onclick = function () {clearInterval(this.timer); // 防止动画累加,要清除动画this.timer = setInterval(() => {let top = win('scrollTop');top -= 20;if (top <= 0) {t = 0;clearInterval(this.timer);}win('scrollTop', top);}, 10)};
四、图片渐现
- 用 js 实现让一张图片慢慢出现
- HTML代码
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Title</title><style>.img-con {width: 500px;height: 335px;background-color: #999999;}img {opacity: 0;}</style></head><body><div class="img-con"><img src="leo.jpg" alt=""></div><script src="js/utils.js"></script><script src="js/3-图片渐现.js"></script></body></html>
- JS 代码
// 1. 导入工具方法const {css} = window.utils;// 2. 获取元素let img = document.querySelector('.img-con > img');// 3. 设定定时器启动动画let timer = setInterval(() => {// 3.1 获取当前元素的透明度let op = +css(img, 'opacity');// 3.2 给透明度累加,并判断累加后的值op += 0.01;if (op >= 1) {clearInterval(timer);op = 1;}// 3.3 把累加后的值设置回去css(img, 'opacity', op);}, 16);
五、匀速动画
- 需求:让页面中的盒子在 2s 内从起始位置匀速运动到 left 是 800 的位置
- 匀速运动中速度是一定的,时间时固定的,所以最为关键的是求出路程,然后再求出速度;
const {css} = window.utils;let box = document.getElementById('box');// 过度时间let duration = 2000;// 目标值let target = 800;// 起始位置let begin = css(box, 'left');// 总移动距离let change = target - begin;// 记录当前时间let time = 0;let interval = 16;let timerId = setInterval(() => {time += 10;if (time >= duration) {css(box, 'left', target);clearInterval(timerId);return}let curLeft = change / duration * time + begin;css(box, 'left', curLeft)}, interval);
- 匀速运动中某一时刻的位置计算
function linear(curTime, begin, change, duration) {// 计算匀速运动时,元素某一时刻的位置return (change / duration) * curTime + begin;}
六、多方向的匀速动画
- 让页面中的 div 在 2s 内运动到的 left 值是 850,top 值是 500 的位置;
- 多方向的匀速动画即元素的多个 js 属性同时变化
const {css} = window.utils;// 过度时间 2000let duration = 2000;// 目标值let targetLeft = 800;let targetTop = 500;// 获取起始位置let beginLeft = css(box, 'left');let beginTop = css(box, 'top');// 获取总路程let changeLeft = targetLeft - beginLeft;let changeTop = targetTop - beginTop;// 记录时间let time = 0;// 定时器执行间隔const interval = 16;let timerId = setInterval(() => {time += interval;// 动画结束条件判断if (time >= duration) {css(box, {left: targetLeft,top: targetTop});clearInterval(timerId);return;}// 计算当前时刻元素 left 和 top 的值let curLeft = linear(time, beginLeft, changeLeft, duration);let curTop = linear(time, beginTop, changeTop, duration);css(box, {left: curLeft,top: curTop})}, interval);function linear(curTime, begin, change, duration) {// 计算匀速运动时,元素某一时刻的位置return (change / duration) * curTime + begin;}
