文章目录
一、缓动动画
1、缓动动画原理
匀速动画 : 之前的博客 【Web APIs】JavaScript 动画 ① ( setInterval 实现动画原理 | 动画函数封装 | 元素自定义属性接收定时器标识 ) 中 实现的动画 是 匀速动画 , 为 obj 元素设置的 定时器 每次 向前移动 1 像素 ;
javascript
obj.style.left = obj.offsetLeft + 1 + 'px';
该动画的 移动步长 是 1 像素 , 也就是 每隔 30 ms 向前移动 1 像素 ;
" 匀速动画 " 的 原理是 " 元素盒子位置 + 固定值步长 " ;
与 匀速动画 相对的是 " 缓动动画 " , 缓动动画 的 原理是 " 元素盒子位置 + 不固定值步长 " ;
不固定步长值计算 , 需要 将 计算过程 写到 定时器 中 , target 是 动画目的地位置 , obj.offsetLeft 是 当前的元素位置 , 移动的 步长是 " 动画目的地位置 - 当前的元素位置 " 的 十分之一 长度 ;
每次计算出来的 步长 是不同的 , 每一次计算出来的步长 , 都比前一次要短 ;
javascript
// 步长值计算 : 将 计算过程 写到定时器 函数里面
var step = (target - obj.offsetLeft) / 10;
每隔 30 ms 执行定时器时 , 修改 元素的 left 值 , 每次增加 计算出的 step 步长值 , 实现缓动动画效果 ;
javascript
// 操作对象 : 从具体的 div.style.left 改为形参传入的 obj.style.left 参数
// 每次定时器执行时 , 修改元素的 left 值 , 实现动画效果
// 每次增加 计算出的 step 步长值 , 实现缓动效果
obj.style.left = obj.offsetLeft + step + 'px';
2、代码示例
代码示例 :
html
<!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>缓动动画</title>
<style>
div {
/* 绝对定位 元素 优先以 最近的 已定位 祖先元素 为基准 , 无则以 视口 ( body 元素 ) 为基准 ; */
position: absolute;
/* 该属性就是实现动画时 , 实时改变的属性 */
/* 初始左侧偏移量 : 动画起始位置 , 后续JS会实时修改该值实现移动 */
left: 0;
/* 元素的 大小 和 样式 */
/* 元素宽度 : 固定尺寸 , 仅做样式展示 */
width: 100px;
/* 元素高度 : 固定尺寸 , 仅做样式展示 */
height: 100px;
/* 背景颜色 : 设置粉色 , 区分元素视觉效果 */
background-color: pink;
}
</style>
</head>
<body>
<!-- 动画在载体元素 1 -->
<div></div>
<script>
// 匀速动画 : 元素盒子位置 + 固定值步长
// 缓动动画 : 元素盒子位置 + 不固定值步长
// 形参 obj : 接收要做动画的 DOM 元素 ( 如 : div、span )
// 形参 target : 接收动画的终止位置 ( 如 : 300、200 )
function animate(obj, target) {
// 定时器标识 : 用于清除定时器 , 避免多个定时器同时运行
obj.timer = setInterval(function() {
// 不固定步长值计算 : 将 计算过程 写到定时器 函数里面
var step = (target - obj.offsetLeft) / 10;
// 步长值取整 : 向上取整 / 向下取整
// 步长值为正数 , 向右运动 , 必须向上取整 , 否则会出现动画向左回退的现象
// 步长值为负数 , 向左运动 , 必须向下取整 , 否则会出现动画向右回退的现象
//step = step > 0 ? Math.ceil(step) : Math.floor(step);
// 终止条件:从固定 400px 改为动态的 target 参数
if (obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
// 操作对象 : 从具体的 div.style.left 改为形参传入的 obj.style.left 参数
// 每次定时器执行时 , 修改元素的 left 值 , 实现动画效果
// 每次增加 计算出的 step 步长值 , 实现缓动效果
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
// 获取要做动画的 DOM 元素
var div = document.querySelector('div');
// 调用动画函数, 为两个 DOM 元素分别设置动画
animate(div, 300);
// 调试 : 打印定时器标识 , 便于调试
console.log(div.timer);
</script>
</body>
</html>
执行结果 :

二、步长计算取整
1、步长计算取整
设置缓动动画 移动 300 像素后 , 最终 div 元素停留在的位置 对应的 left 属性值是 296.4px ;

在页面中 , 如果出现最终位置不是整数 , 导致 多个元素无法 对齐 的情况 ;
步长取整 , 需要考虑 步长值 是 正数 和 负数 的情况 :
- 步长值为正数 , 向右运动 , 必须向上取整 , 否则会出现动画向左回退的现象 ;
- 步长值为负数 , 向左运动 , 必须向下取整 , 否则会出现动画向右回退的现象 ;
javascript
// 步长值取整 : 向上取整 / 向下取整
// 步长值为正数 , 向右运动 , 必须向上取整 , 否则会出现动画向左回退的现象
// 步长值为负数 , 向左运动 , 必须向下取整 , 否则会出现动画向右回退的现象
step = step > 0 ? Math.ceil(step) : Math.floor(step);
2、代码示例
代码示例 :
html
<!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>缓动动画</title>
<style>
div {
/* 绝对定位 元素 优先以 最近的 已定位 祖先元素 为基准 , 无则以 视口 ( body 元素 ) 为基准 ; */
position: absolute;
/* 该属性就是实现动画时 , 实时改变的属性 */
/* 初始左侧偏移量 : 动画起始位置 , 后续JS会实时修改该值实现移动 */
left: 0;
/* 元素的 大小 和 样式 */
/* 元素宽度 : 固定尺寸 , 仅做样式展示 */
width: 100px;
/* 元素高度 : 固定尺寸 , 仅做样式展示 */
height: 100px;
/* 背景颜色 : 设置粉色 , 区分元素视觉效果 */
background-color: pink;
}
</style>
</head>
<body>
<!-- 动画在载体元素 1 -->
<div></div>
<script>
// 匀速动画 : 元素盒子位置 + 固定值步长
// 缓动动画 : 元素盒子位置 + 不固定值步长
// 形参 obj : 接收要做动画的 DOM 元素 ( 如 : div、span )
// 形参 target : 接收动画的终止位置 ( 如 : 300、200 )
function animate(obj, target) {
// 定时器标识 : 用于清除定时器 , 避免多个定时器同时运行
obj.timer = setInterval(function() {
// 不固定步长值计算 : 将 计算过程 写到定时器 函数里面
var step = (target - obj.offsetLeft) / 10;
// 步长值取整 : 向上取整 / 向下取整
// 步长值为正数 , 向右运动 , 必须向上取整 , 否则会出现动画向左回退的现象
// 步长值为负数 , 向左运动 , 必须向下取整 , 否则会出现动画向右回退的现象
step = step > 0 ? Math.ceil(step) : Math.floor(step);
// 终止条件:从固定 400px 改为动态的 target 参数
if (obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
// 操作对象 : 从具体的 div.style.left 改为形参传入的 obj.style.left 参数
// 每次定时器执行时 , 修改元素的 left 值 , 实现动画效果
// 每次增加 计算出的 step 步长值 , 实现缓动效果
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
// 获取要做动画的 DOM 元素
var div = document.querySelector('div');
// 调用动画函数, 为两个 DOM 元素分别设置动画
animate(div, 300);
// 调试 : 打印定时器标识 , 便于调试
console.log(div.timer);
</script>
</body>
</html>
执行结果 :
