JavaScript缓动函数是通过数学公式控制动画随时间变化速率的工具,核心作用是将线性时间映射为非线性的值变化,让动画更符合人眼的视觉习惯。时间参数作为缓动函数的核心输入,其管理精度直接影响动画的最终效果。

缓动函数的基本结构与时间参数含义
标准的缓动函数通常接收四个核心参数,其中时间参数是决定动画进度的关键,函数的基本结构如下:
/**
* 缓动函数通用结构
* @param {number} t 当前时间,取值范围通常为0到持续时间d
* @param {number} b 动画起始值
* @param {number} c 动画变化总量,即结束值减去起始值
* @param {number} d 动画总持续时间
* @returns {number} 当前时间对应的动画值
*/
function easingFunction(t, b, c, d) {
// 时间参数归一化处理,得到0到1的进度值
const progress = t / d;
// 根据进度计算缓动后的值
const easedProgress = customEasingLogic(progress);
return b + c * easedProgress;
}
这里的t就是核心时间参数,代表动画从开始到当前时刻经过的时间,d是动画的总时长,两者的比值t/d是时间归一化后的进度,所有缓动计算都基于这个归一化进度展开。
时间参数的精确管理方法
1. 时间参数的归一化与边界处理
为了避免时间参数超出合理范围导致动画异常,需要先对时间参数做归一化和边界限制:
function safeEasing(t, b, c, d) {
// 限制时间参数在0到d之间,避免超出范围
const clampedT = Math.max(0, Math.min(t, d));
// 归一化时间,得到0到1的进度
const normalizedT = clampedT / d;
// 二次缓动逻辑:progress * progress
const easedProgress = normalizedT * normalizedT;
return b + c * easedProgress;
}
2. 基于requestAnimationFrame的时间更新
在浏览器中实现动画时,应该使用requestAnimationFrame来更新时间参数,保证时间参数和浏览器的刷新率同步,避免动画卡顿:
function runAnimation(element, startValue, endValue, duration, easingFn) {
const startTime = performance.now();
function update(currentTime) {
// 计算当前经过的时间t
const t = currentTime - startTime;
if (t < duration) {
// 调用缓动函数计算当前值
const currentValue = easingFn(t, startValue, endValue - startValue, duration);
element.style.transform = `translateX(${currentValue}px)`;
// 继续下一帧更新
requestAnimationFrame(update);
} else {
// 动画结束,设置最终值
element.style.transform = `translateX(${endValue}px)`;
}
}
requestAnimationFrame(update);
}
常见缓动函数的时间参数应用示例
不同的缓动函数对时间参数的处理逻辑不同,以下是两种常见缓动函数的实现:
线性缓动
线性缓动的时间参数直接映射为进度,没有速率变化:
function linearEasing(t, b, c, d) {
const progress = t / d;
return b + c * progress;
}
弹性缓动
弹性缓动会在时间参数接近结束时加入震荡效果,需要对归一化后的时间做特殊处理:
function elasticEasing(t, b, c, d) {
const progress = t / d;
if (progress === 0 || progress === 1) return b + c * progress;
// 弹性震荡的时间处理逻辑
const decay = Math.pow(2, -10 * progress);
const oscillation = Math.sin((progress * 10 - 0.75) * (2 * Math.PI) / 3);
return b + c * (1 + decay * oscillation);
}
时间参数的实际应用场景
1. 同步多个动画的时间参数
当需要多个元素同时执行动画且节奏一致时,可以共享同一个时间参数:
function syncMultiAnimation(elements, startValues, endValues, duration, easingFn) {
const startTime = performance.now();
function update(currentTime) {
const t = currentTime - startTime;
elements.forEach((el, index) => {
const currentValue = easingFn(t, startValues[index], endValues[index] - startValues[index], duration);
el.style.opacity = currentValue;
});
if (t < duration) {
requestAnimationFrame(update);
}
}
requestAnimationFrame(update);
}
2. 可暂停可恢复的时间参数管理
实现可暂停的动画时,需要记录累计经过的时间,暂停时停止更新时间参数,恢复时重新计算起始时间:
class PausableAnimation {
constructor(element, startVal, endVal, duration, easingFn) {
this.element = element;
this.startVal = startVal;
this.endVal = endVal;
this.duration = duration;
this.easingFn = easingFn;
this.paused = false;
this.accumulatedTime = 0;
this.startTime = null;
this.rafId = null;
}
start() {
this.startTime = performance.now() - this.accumulatedTime;
const update = (currentTime) => {
if (this.paused) return;
const t = currentTime - this.startTime;
if (t < this.duration) {
const val = this.easingFn(t, this.startVal, this.endVal - this.startVal, this.duration);
this.element.style.transform = `translateY(${val}px)`;
this.rafId = requestAnimationFrame(update);
} else {
this.element.style.transform = `translateY(${this.endVal}px)`;
}
};
this.rafId = requestAnimationFrame(update);
}
pause() {
this.paused = true;
cancelAnimationFrame(this.rafId);
this.accumulatedTime = performance.now() - this.startTime;
}
resume() {
this.paused = false;
this.start();
}
}
时间参数管理的注意事项
- 时间参数
t的单位需要和总时长d的单位保持一致,通常都使用毫秒 - 避免在动画循环中手动修改时间参数的增量,应该基于实际经过的时间计算,避免累计误差
- 当动画总时长
d为0时,需要特殊处理,直接返回结束值,避免除以0的错误 - 如果缓动函数需要在服务端使用,注意
performance.now()的兼容性,可以替换为Date.now()计算时间差
JavaScript缓动函数时间参数easing_function修改时间:2026-07-20 01:09:34