JavaScript 实现元素减速运动效果实例
本文通过两个具体的 JavaScript 示例,解析如何实现网页 DOM 元素的减速运动缓冲效果。第一种方法模拟物理加速度过程,第二种方法基于剩余距离的比例递减速度,帮助开发者在游戏编程或界面交互中实现更自然的动画体验。
结果或目标
在网页页面中,通过纯 JavaScript 代码控制 div 元素从起始位置平滑移动到目标位置,且在移动过程中速度逐渐降低,呈现“刹车”式的缓冲停止效果,而非匀速直线运动。
准备条件
一个支持 HTML/DOM 操作的浏览器环境。
具备基本的 JavaScript 语法知识,特别是定时器
setTimeout的使用和闭包概念。了解基本的 CSS 定位属性,如
position: relative和position: absolute。
真实操作顺序
第1步:构建基础 HTML 结构
首先需要创建两个带有边框的容器,内部各包含一个绝对定位的子 div,用于展示减速动画的效果。同时设置显示坐标变化的区域。aa 为红色背景方块,bb 为蓝色背景方块。
注意: 以下代码保留了原始示例的结构逻辑,但去除了冗余的代码标签包装,使其更符合现代标准。
<!-- 第一个减速方块的容器 -->
<div style="position:relative; border:1px solid #000; width:550px; height:50px; overflow:hidden;">
<div id="aa" style="width:50px; height:50px; background:#930; position:absolute; left:0px; top:0px;"></div>
</div>
<div id="x-display"></div>
<!-- 第二个减速方块的容器 -->
<div style="position:relative; border:1px solid #000; width:550px; height:50px; overflow:hidden;">
<div id="bb" style="width:50px; height:50px; background:#0000FF; position:absolute; left:0px; top:0px;"></div>
</div>
<div id="y-display"></div>
第2步:定义工具函数与变量初始化
定义一个简单的 ID 获取辅助函数,并初始化控制运动的参数。
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
// 第一个动画相关变量
var start1 = 0; // 起始位置
var distance1 = 500; // 总移动距离
var totalTime = 300; // 预估总时间(帧数)
var acceleration = 2 * distance1 / (totalTime * totalTime); // 加速度系数
var obj1 = $("aa"); // 目标元素
var currentPos1 = 0; // 当前位置
var frameCount = 0; // 当前帧计数
// 第二个动画相关变量
var totalDistance2 = 500;
var obj2 = $("bb");
var currentPos2 = 0;
第3步:实施基于物理公式的第一种减速算法
此方法使用物理学中的位移公式:$S = V_0t + \frac{1}{2}at^2$。假设初速度为0,随着时间推移,位移增加的速度会加快?不对,我们需要的是减速。
纠正说明: 原文代码实现的其实是先加速后减速或者单纯的加速直到终点停止的逻辑并不完全符合直觉上的“匀减速”。让我们仔细看代码:
i = parseInt((a*tt)*t - .5 * a * (t*t));
这是一个开口向下的抛物线。当 t 较小时,线性项主导;当 t 较大时,平方项主导导致增长变缓甚至减少。但在本例的循环退出条件前,它主要表现为一种非线性的加速然后趋于平稳的效果,并非纯粹的匀减速。为了忠实于原文意图并修正其表述,我们将其描述为“基于多项式函数的非线性运动”,它实现了运动过程中的速率变化(在此特定参数下表现为最后阶段的平缓)。
function run1() {
frameCount++;
// 核心计算公式:利用二次函数产生非线性位移
var displacement = Math.floor((acceleration * totalTime) * frameCount - 0.5 * acceleration * (frameCount * frameCount));
// 判断是否到达终点
if (displacement >= distance1) {
obj1.style.left = (start1 + distance1) + "px";
return; // 动画结束
}
// 更新 DOM 位置
obj1.style.left = (start1 + displacement) + "px";
$("x-display").innerHTML += displacement + ",";
// 持续调用,控制刷新频率(10ms 约等于 100FPS,实际浏览器渲染受限于屏幕刷新率)
setTimeout(run1, 10);
}
run1();
运行效果观察: 红色方块将开始移动,并在控制台或页面上输出其经过的路径点序列。图片展示了这一动态过程的某一帧状态。
第4步:实施基于距离比例的第四种减速算法
这种方法更为直观地模拟了“接近目标时速度变慢”的物理现象。每次移动的距离是当前剩余距离的一个固定百分比(例如 1%)。这是一种几何级数的收敛过程,永远无法在有限步骤内真正“到达”数学上的终点,因此需要设置一个阈值来判断动画结束。
function run2() {
var remainingDistance = totalDistance2 - currentPos2;
// 计算每一步的移动量:剩余距离的 1/100
var stepSize = remainingDistance / 100;
// 如果步长太小但不为零,设为最小步进值1像素,避免卡顿感
if (stepSize > 0 && stepSize < 1) {
stepSize = 1;
};
// 判断是否应该停止
if (stepSize == 0 || currentPos2 + stepSize >= totalDistance2) {
obj2.style.left = (start1 + totalDistance2) + "px";
return;
}
// 更新位置
currentPos2 += stepSize;
obj2.style.left = (start1 + currentPos2) + "px";
$("y-display").innerHTML += parseInt(currentPos2 + stepSize) + ",";
// 递归调用
setTimeout(run2, 10);
}
run2();
完成判断
当两个方块的 left 属性最终稳定在容器宽度范围内,且后续代码不再触发 setTimeout 递归调用时,即表示减速运动效果执行完毕。
简要总结
上述两种方法分别代表了不同的动画曲线生成思路:
- 公式法: 通过预定义的数学函数(如抛物线、正弦波等)直接计算每一帧的位置,适合轨迹固定的动画。
- 比例衰减法: 根据当前状态动态计算下一步增量,适合需要根据用户交互实时调整的动画,其自然的渐停特性非常符合人类对惯性运动的认知。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









