tween.js 快速上手:安装引入与第一个补间动画示例
针对 tween.js 的入门实用教程,详细讲解 npm 与 CDN 两种安装引入途径、补间动画数据驱动机制,并通过完整的位移动画代码示例带你快速上手 tween.js。
tween.js 是一个轻量级且高效的 JavaScript 补间动画库,专门负责在指定时间内平滑计算对象属性的连续过渡。本文直接面向初次接触 tween.js 的开发者,讲解其核心工作机制、现代工程与原生页面的多种引入方式,并一步步完成第一个平滑移动的补间动画示例,帮助你快速掌握这套开箱即用的补间动画工具。
一、核心认知:tween.js 的工作原理与职责边界
在开始编写动画前,首先需要明确一个关键概念:补间动画(Tweening / In-betweening)究竟在做什么? 在传统关键帧动画中,我们通常只设定起止两个关键状态,而中间过程的每一帧画面都是计算得出的。tween.js 承担的就是这个“插值计算器”的角色。
需要特别注意的是,tween.js 本身不绑定任何具体的渲染技术。它不关心最终被渲染的是 HTML DOM 元素、Canvas 2D 路径,还是 Three.js 中的三维网格模型(Mesh)。它的工作对象是一个普通的 JavaScript 对象,其内部工作闭环如下:
- 定义起点与终点:设定一个包含数值属性的普通对象作为初始状态,并指定目标终态数值与过渡时间(毫秒)。
- 时间比率插值:在补间生命周期内,根据经过的时间与总时长的比值,结合缓动函数(Easing)算出当前时刻的归一化参数。
- 改写数据与回调触发:逐帧修改源对象的属性值,并触发
onUpdate回调函数。 - 消费数据并更新视图:开发者在
onUpdate回调中获取修改后的最新数值,手动赋值给元素的style.transform、Canvas 绘图上下文或 3D 对象的坐标属性。
这种“数据运算”与“视图渲染”高度解耦的设计,使得 tween.js 体积极其精简,同时在跨平台与不同渲染引擎之间具备广泛的通用性。
二、环境接入:tween.js 的安装与多种引入方式
根据你的项目工程类型,可以选择通过包管理器安装,或者直接使用 CDN 标签在单页面中载入。两者的核心 API 与使用逻辑完全一致。
1. 现代前端工程化引入(推荐)
在基于 Vite、Webpack、Rollup 等构建工具的 Vue、React 或原生现代项目中,推荐通过官方 npm 依赖包进行安装。请注意,目前社区维护的官方最新包名带有组织作用域 @tweenjs/tween.js:
# 使用 npm
npm install @tweenjs/tween.js
# 或者使用 pnpm / yarn
pnpm add @tweenjs/tween.js
yarn add @tweenjs/tween.js
安装完成后,在需要使用动画的 JavaScript 或 TypeScript 模块中使用标准 ES Module 语法引入:
import * as TWEEN from '@tweenjs/tween.js';
该包自带完善的 TypeScript 类型定义文件,IDE 会提供完整的代码补全与参数类型提示。若需要进行打包体积优化(Tree-shaking),也可以按需仅导入核心类:
import { Tween, Easing, update } from '@tweenjs/tween.js';
2. 原生 HTML 单页面与原型快速开发(CDN 引入)
如果你正在编写一个纯静态页面、教学演示 demo,或者不想搭建复杂的构建工程,可以直接在 HTML 文件中使用 <script> 标签引入 CDN 提供的 UMD 构建版本:
<!-- 引入 tween.js 的 UMD 生产版本 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/20.0.0/tween.umd.js"></script>
通过这种方式引入后,浏览器全局上下文中会自动挂载 window.TWEEN。你可以在浏览器的开发者工具控制台(Console)中直接输入 console.log(TWEEN),如果看到输出了包含 Tween、Easing、Group 等核心属性的对象,即代表引入成功。
三、实战开发:构建你的第一个补间动画
接下来,我们将通过一个具体的例子让一个方块元素从左向右平滑移动 300 像素,并在移动过程中逐渐增大。整个编码过程分为清晰的四个步骤。
步骤拆解
- 创建数据对象:定义一个变量存储动画实时的数值状态,例如
const coords = { x: 0, scale: 1 };。 - 构建 Tween 实例并配置目标:调用
new TWEEN.Tween(coords),通过.to({ x: 300, scale: 1.2 }, 1500)指定目标属性与 1500 毫秒的持续时长,并指定缓动曲线为TWEEN.Easing.Quadratic.Out。 - 绑定更新监听:调用
.onUpdate(() => { ... }),在回调中将计算后的coords.x和coords.scale应用到目标 DOM 的transform样式上。 - 启动补间并维持帧循环:调用
tween.start()启动动画;随后利用浏览器的requestAnimationFrame持续调用TWEEN.update()驱动运算。
完整可运行的单文件示例代码
将以下代码保存为本地的 index.html,直接双击使用任意现代浏览器打开即可查看平滑运动效果:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>tween.js 第一个补间动画示例</title>
<style>
body {
font-family: sans-serif;
padding: 40px;
background: #F3F6FA;
}
.stage {
position: relative;
width: 500px;
height: 160px;
background: #FFFFFF;
border: 1px solid #CAD6E2;
border-radius: 8px;
padding: 20px;
margin-bottom: 20px;
}
#box {
width: 60px;
height: 60px;
background: #6B88A6;
color: #FFFFFF;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
user-select: none;
will-change: transform;
}
button {
background: #71A397;
color: #FFFFFF;
border: none;
padding: 10px 18px;
border-radius: 6px;
font-size: 14px;
cursor: pointer;
}
button:hover {
background: #527E74;
}
</style>
<!-- 引入 tween.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/20.0.0/tween.umd.js"></script>
</head>
<body>
<div class="stage">
<div id="box">BOX</div>
</div>
<button id="playBtn">开始补间动画</button>
<script>
const box = document.getElementById('box');
const playBtn = document.getElementById('playBtn');
// 1. 定义动画初始状态数据(必须是包含数值的纯对象)
const coords = { x: 0, scale: 1 };
// 2. 实例化 Tween 并链式配置目标值、时长与缓动模式
const tween = new TWEEN.Tween(coords)
.to({ x: 300, scale: 1.25 }, 1500)
.easing(TWEEN.Easing.Quadratic.Out)
.onUpdate(() => {
// 3. 在每帧更新时将数值赋值给 DOM 的 CSS transform
box.style.transform = `translate3d(${coords.x}px, 0, 0) scale(${coords.scale})`;
})
.onComplete(() => {
console.log('补间动画执行完成!');
});
// 4. 建立浏览器逐帧刷新循环(核心动力源)
function animate(time) {
requestAnimationFrame(animate);
TWEEN.update(time);
}
requestAnimationFrame(animate);
// 点击按钮重置并触发动画
playBtn.addEventListener('click', () => {
coords.x = 0;
coords.scale = 1;
tween.stop(); // 防止多次重复点击冲突
tween.start();
});
</script>
</body>
</html>
当你点击“开始补间动画”按钮后,方块会迅速起步,随后以自然减速(Quadratic.Out)的姿态平滑滑动到 300 像素的位置并略微放大,控制台在 1.5 秒后输出“补间动画执行完成”。如果你希望使用硬件加速提升动画帧率,请优先使用 translate3d 或 transform 而不是修改 left 或 margin-left。
四、避坑指南:初学者最常遇到的三大疑问排查
虽然 tween.js 的 API 设计直观,但初学者在实际运用中往往会因为帧更新机制或引用关系产生困惑。以下是最高频的三个问题及其解决办法:
1. 为什么调用了 start(),屏幕上的元素却纹丝不动?
这是超过 90% 的初学者都会遭遇的问题。其根本原因在于:tween.js 内部没有常驻定时器。它依赖外部定时调用 TWEEN.update() 来推进时间。
如果你只执行了 tween.start(),但没有编写 requestAnimationFrame(animate) 并执行 TWEEN.update(),动画内部的当前时间便不会递增,属性自然无法发生改变。请确保页面中有活跃运行的 RAF 帧循环。
2. 为什么元素没有动画过渡,而是“瞬间瞬移”到终点?
出现瞬间跳变通常有两个原因:
- 时间单位传错:
.to()的第二个参数duration的单位是毫秒(ms)。如果传递了1(误以为是 1 秒),动画将在 1 毫秒内计算完成,视觉上表现为瞬移。1 秒应明确传入1000。 - 直接传入了不可解析的字符串:例如传入了
{ x: '300px' }。补间目标值必须是纯数值(如300),不能带 CSS 测量单位。单位应在onUpdate回调做字符串拼接时补上。
3. 能不能在 requestAnimationFrame 循环体内执行 new Tween()?
绝对不能。new TWEEN.Tween() 和 .start() 是配置与触发动作,应当在事件响应(如按钮点击、页面初始化)时执行一次。如果在每秒执行 60 次的 animate 循环体内不断 new 实例,会导致动画队列短时间内堆积成千上万个补间,造成内存暴涨与浏览器严重卡顿。
五、常用缓动函数与进阶扩展
通过修改 .easing() 中的缓动算法,可以赋予动画完全不同的质感。tween.js 内置了包括 Linear、Quadratic、Cubic、Quartic、Quintic、Sinusoidal、Exponential、Circular、Elastic、Back 和 Bounce 在内的丰富函数库,每种曲线都包含 In(加速)、Out(减速)和 InOut(先加速后减速)三种变体:
| 缓动名称 | 典型效果 | 常见应用场景 |
|---|---|---|
TWEEN.Easing.Linear.None |
匀速运动,无加减速 | 机械转盘、无缝滚动背景、进度条 |
TWEEN.Easing.Quadratic.Out |
缓出效果,起步快、平滑减速刹车 | 弹窗展开、抽屉菜单滑出、按钮 hover 状态 |
TWEEN.Easing.Back.Out |
回弹效果,到达终点后轻微冲过并拉回 | 卡片翻转、气泡弹出、强化点击反馈 |
TWEEN.Easing.Bounce.Out |
弹跳落地效果,模拟皮球撞击地面 | 掉落提示卡片、生动趣味引导动效 |
在掌握了基础位移与帧循环后,你可以进一步尝试通过 tweenA.chain(tweenB) 实现补间链式衔接,或者结合 Three.js 的 camera.position 构建三维视角的平滑漫游。无论场景多么复杂,其底层始终遵循“定义数据、配置目标、帧循环驱动、视图消费”的核心链路。
JS怎么使用classList添加、删除和切换class
2026-11-05 17:26:02
网页开发三者分工:HTML结构、CSS样式与JavaScript交互怎么协作
2026-11-05 12:51:22
JS解析URL参数时怎么处理中文乱码和特殊字符
2026-11-05 12:47:23
js-cookie 存储 JSON 对象:自动序列化与反序列化技巧
2026-11-05 12:36:26
marked.js 快速上手:安装与基础 Markdown 转 HTML 示例
2026-11-05 09:32:53








