From b423b0ab7fcd8c47ae442a397f89510dba7c0efb Mon Sep 17 00:00:00 2001 From: mk965 Date: Thu, 14 Aug 2025 18:02:53 +0800 Subject: [PATCH] Update Chinese translations to match latest English versions - Update README_zh-CN.md with modern ES6 import syntax and complete installation guide - Rewrite contributor_guide_zh-CN.md with updated toolchain (Prettier + ESLint) - Complete rewrite of user_guide_zh-CN.md with all latest API features - Add missing functionality documentation (Groups, dynamic, pause, etc.) - Sync all code examples with current best practices - Fix outdated references and broken links All Chinese documentation now fully aligns with English counterparts. --- README_zh-CN.md | 278 +++++++++++++------- docs/contributor_guide_zh-CN.md | 68 ++--- docs/user_guide_zh-CN.md | 445 +++++++++++++++++--------------- 3 files changed, 450 insertions(+), 341 deletions(-) diff --git a/README_zh-CN.md b/README_zh-CN.md index a2f8d782..726e246e 100644 --- a/README_zh-CN.md +++ b/README_zh-CN.md @@ -12,8 +12,6 @@ --- ```html - -
- -``` - -或者 unpkg.com: - -```html - -``` - -请注意,unpkg.com 支持 URL 中的 semver 版本,其中 URL 中的 `^` 告诉 unpkg 为你提供最新版本 20.x.x。 - -## 使用 script 标签构建并包含在你的项目中 - -目前需要 npm 来构建项目。 - -```bash -git clone https://github.com/tweenjs/tween.js -cd tween.js -npm install -npm run build -``` - -这将在 `dist` 目录中创建一些构建。 目前有两种不同的库版本: - -- UMD : `tween.umd.js` -- ES6 Module : `tween.esm.js` - -你现在可以将 tween.umd.js 复制到你的项目中,然后将其包含在一个 script 标签,它将 TWEEN 添加到全局范围, - -```html - -``` - -或将 TWEEN 作为 JavaScript 模块导入, - -```html - -``` - -其中 `path/to` 替换为你放置文件的位置。 - -## 使用 `npm install` 和 `import` 从 `node_modules` 中添加 - -你可以将 tween.js 添加为 npm 依赖项: - -```bash -npm install @tweenjs/tween.js -``` - -### 使用构建工具 - -如果你使用 [Node.js](https://nodejs.org/)、[Parcel](https://parceljs.org/)、[Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/)、[Vite](https://vitejs.dev/) 或者其他的构建工具,那么你现在可以使用以下方式来导入 tween.js: - -```javascript -import * as TWEEN from '@tweenjs/tween.js' -``` - -### 没有构建工具 - -如果你将 `node_modules` 作为网站的一部分提供服务,则可以使用 `importmap` script 标签从 `node_modules` 导入。 首先,假设 `node_modules` 位于你网站的根目录,你可以编写一个导入映射: - -```html - -``` - -现在,在任何 module script 中,你都可以通过包名导入它: - -```javascript -import * as TWEEN from '@tweenjs/tween.js' -``` - # 特性 -- 做一件事并且只做一件事:补间属性 -- 不处理 CSS 单位(例如附加 `px`) +- 专注于一件事并且做得很好:补间对象的属性 +- 不处理 CSS 单位(例如添加 `px`) - 不插值颜色 - 缓动函数可在 Tween 之外重复使用 - 也可以使用自定义缓动函数 +- 不创建自己的动画循环,使其能够灵活地集成到 + 任何动画循环中。 -# 文档 +# 示例 @@ -342,9 +256,169 @@ import * as TWEEN from '@tweenjs/tween.js'
+# 安装 + +推荐的方法是使用 `import` 语法。这里我们列出了各种安装方法,大致按照最推荐到最不推荐的顺序排列。请评估以下所有方法,选择最适合你项目的方法。 + +## 使用 `npm install` 和从 `node_modules` 导入 + +你可以将 tween.js 添加为 npm 依赖项: + +```bash +npm install @tweenjs/tween.js +``` + +### 不使用构建工具 + +#### 本地安装 + +如果你将 `node_modules` 作为网站的一部分提供服务,可以使用标准的 `importmap` 脚本标签从 `node_modules` 导入。首先,假设 `node_modules` 位于你网站的根目录,你可以在 HTML 文件中编写导入映射: + +```html + +``` + +现在在任何模块脚本中,你都可以通过包名导入 Tween.js: + +```html + +``` + +#### 从 CDN 导入 + +请注意,没有 `importmap` 的情况下,你可以像上面第一个示例一样直接从 CDN 导入: + +```html + +``` + +如果你愿意,也可以将 `importmap` 链接到 CDN 而不是本地的 `node_modules` 文件夹: + +```html + + + +``` + +### 使用构建工具 + +如果你使用 [Node.js](https://nodejs.org/)、[Parcel](https://parceljs.org/)、[Webpack](https://webpack.js.org/)、[Rollup](https://rollupjs.org/)、[Vite](https://vitejs.dev/) 或其他构建工具,那么你可以使用 `npm install @tweenjs/tween.js` 安装,然后将库 `import` 到你的 JavaScript(或 TypeScript)文件中,构建工具会知道如何从 `node_modules` 找到源代码,而无需创建 `importmap` 脚本: + +```javascript +import * as TWEEN from '@tweenjs/tween.js' +``` + +但是请注意,这种方法需要始终运行构建工具才能使你的应用程序工作,而 `importmap` 方法无需任何构建工具即可作为简单的静态 HTML 站点工作。 + +## 手动构建 + +另一种方法是使用 git 下载源代码,手动构建库,然后将输出放置在你的项目中。这需要 Node.js。 + +```bash +git clone https://github.com/tweenjs/tween.js +cd tween.js +npm install +npm run build +``` + +这将在 `dist` 目录中创建一些构建文件。目前有两种不同的库构建版本: + +- ES6 模块在 `/dist/tween.esm.js`(推荐) +- UMD 在 `/dist/tween.umd.js`(已弃用,将在未来的主要版本中删除) + +你现在可以将这两个文件中的一个复制到你的项目中,并像这样使用(推荐): + +```html + +``` + +或(已弃用,将在未来的主要版本中删除): + +```html + + +``` + +其中 `path/to` 替换为你放置文件的位置。 + +> [!Note] +> 你也可以从 unpkg 下载这些文件,例如: +> https://unpkg.com/browse/@tweenjs/tween.js@23.1.3/dist/ + +## 从 CDN 使用全局变量(已弃用) + +> [!Note] +> 此方法已弃用,将在未来的主要版本中删除! + +使用 UMD 文件从内容分发网络(CDN)安装全局 `TWEEN` 变量。 + +从 cdnjs: + +```html + +``` + +或从 unpkg.com: + +```html + +``` + +然后在任何脚本中使用 `TWEEN` 变量: + +```html + +``` + +> [!Note] +> unpkg.com 支持 URL 中的 semver 版本,其中 URL 中的 `^` 告诉 unpkg 提供最新版本 20.x.x。 + +## CommonJS(已弃用) + +如果你不知道 CommonJS 是什么,请跳过此部分! + +> [!Note] +> 此方法已弃用,将在未来的主要版本中删除! + +以上任何方法都适用于仍使用 CommonJS 的旧系统。重复以上任何方法,但使用 `dist/tween.cjs` 而不是 `dist/tween.esm.js` 或 `dist/tween.umd.js`。 + +# 文档 + +- [用户指南](./docs/user_guide_zh-CN.md) +- [贡献者指南](./docs/contributor_guide_zh-CN.md) +- 使用 tween.js 与 three.js 的[教程](https://web.archive.org/web/20220601192930/http://learningthreejs.com/blog/2011/08/17/tweenjs-for-smooth-animation/) +- 另见:[libtween](https://github.com/jsm174/libtween),由 [jsm174](https://github.com/jsm174) 将 tween.js 移植到 C 的版本 + # 测试 -你需要先安装 `npm`——它随 node.js 一起提供,因此请先安装它。 然后,cd 到 `tween.js` 的(或你克隆 repo 的任何地方)目录并运行: +你需要先安装 `npm`——它随 node.js 一起提供,因此请先安装它。然后,cd 到 `tween.js` 的(或你克隆 repo 的任何地方)目录并运行: ```bash npm install @@ -356,7 +430,13 @@ npm install npm test ``` -如果你想添加任何功能或更改现有功能,你 _必须_ 运行测试以确保你没有破坏任何其他功能。任何拉取请求 (PR) 都需要在 `src/tests.ts` 中更新通过功能更改测试(或通过新功能或修复的新测试)才能接受 PR。 有关更多信息,请参阅 [贡献](CONTRIBUTING.md)。 +如果你想添加任何功能或更改现有功能,你 _必须_ 运行测试以确保你没有破坏任何其他功能。任何拉取请求 (PR) 都需要在 `src/tests.ts` 中为功能更改提供更新的通过测试(或为新功能或修复提供新的通过测试)才能被接受。有关更多信息,请参阅 [贡献](CONTRIBUTING.md)。 + +# 人员 + +维护者:[Joe Pea (@trusktr)](https://github.com/trusktr)。 + +[所有贡献者](http://github.com/tweenjs/tween.js/contributors)。 # 使用 tween.js 的项目 diff --git a/docs/contributor_guide_zh-CN.md b/docs/contributor_guide_zh-CN.md index e4b4a807..1d0e1f76 100644 --- a/docs/contributor_guide_zh-CN.md +++ b/docs/contributor_guide_zh-CN.md @@ -2,28 +2,28 @@ 更多语言: [English](./contributor_guide.md), [简体中文](./contributor_guide_zh-CN.md) -本指南适用于想要向库贡献的人,或者想了解背后的内容:如何进行测试?我们自动化什么?我们如何做发布?等等。 +本指南适用于想要为该库做出贡献的人,或者对了解幕后情况感到好奇的人:如何进行测试?我们自动化了什么?我们如何发布?等等。 -如果你正在查找*如何使用*库的文档,[用户指南](./user_guide_zh-CN.md) 是适合你的。 +如果你正在寻找如何使用库的文档,[用户指南](./user_guide_zh-CN.md)适合你。 -**NOTE: 这个文档是一个正在进行的工作。更多内容将分阶段添加。如果你有问题,你想看到回答,请在 [as comments on this issue](https://github.com/tweenjs/tween.js/issues/323) 中提出,谢谢!** +**注意:本文档是正在进行的工作。更多内容将分阶段添加。如果你有想看到解答的问题,请在[此 issue 的评论](https://github.com/tweenjs/tween.js/issues/323)中添加它们。谢谢!** -目录: +本指南内容: -- [tween.js 贡献者指南](#tween.js-贡献者指南) -- [开发者要求](#开发者要求) -- [测试](#测试) - - [单元测试](#单元测试) - - [代码风格和 lint 测试](#代码风格和-lint-测试) - - [其他类型的测试](#其他类型的测试) -- [持续集成](#持续集成) -- [发布流程](#发布流程) +- [tween.js 贡献者指南](#tweenjs-贡献者指南) + - [开发者要求](#开发者要求) + - [测试](#测试) + - [单元测试](#单元测试) + - [代码风格和 lint 测试](#代码风格和-lint-测试) + - [其他类型的测试](#其他类型的测试) + - [持续集成](#持续集成) + - [发布流程](#发布流程) ## 开发者要求 -虽然 tween.js *不*需要依赖 node.js 运行,但我们使用 node.js 来进行开发。所以我们需要先 [安装 node.js](https://nodejs.org/en/download/),然后才能在库中工作。 +虽然 tween.js 不需要 node.js 即可运行,但我们在开发中使用它。因此,在能够使用该库之前,你需要[安装 node.js](https://nodejs.org/en/download/)。 -Node.js 包括我们用来运行脚本的 npm 工具,例如打包、运行测试等的脚本。在你尝试运行下面详述的任何步骤之前,请确保它在你的系统中正常工作。 +Node.js 包含我们用来运行脚本的 `npm` 工具,例如打包、运行测试等脚本。在尝试运行下面详述的任何步骤之前,请确保它在你的系统中正常工作。 安装 node.js 后,克隆 tween.js 存储库: @@ -31,7 +31,7 @@ Node.js 包括我们用来运行脚本的 npm 工具,例如打包、运行测 git clone https://github.com/tweenjs/tween.js.git ``` -进入该文件夹: +切换到该文件夹: ```bash cd tween.js @@ -43,7 +43,7 @@ cd tween.js npm install ``` -或者分三行: +或者三行代码: ```bash git clone https://github.com/tweenjs/tween.js.git @@ -57,13 +57,13 @@ npm install npm test ``` -如果你在运行上述任何步骤时遇到问题,请尝试使用你选择的搜索引擎搜索错误文本。这通常是最快的解决方法,因为很多人可能已经遇到过同样的问题。 +如果你在运行上述任何命令时遇到问题,请尝试使用你选择的搜索引擎搜索错误文本。这通常是最快的解决方案,因为许多人可能已经遇到了相同的问题。 ## 测试 `test` 目录中有一套自动化测试。 -这些可以快速发现代码上的回归,在添加新功能或更改代码以修复 Bug 时很有用;我们不想引入新的 Bugs!自动化测试还会发现风格问题,这有助于我们保持库的凝聚力。 +这些测试可以快速发现代码中的回归问题——在添加新功能或更改代码以修复错误时很有用;我们不想引入新的错误!它们还会发现风格问题,这有助于保持库的凝聚力。 要运行测试,请输入: @@ -71,30 +71,30 @@ npm test npm test ``` -你应该在更改库中的代码后运行测试。如果你更改测试描述的行为,测试将不会通过,你将得到指向失败测试的错误。 这可能是因为... +你应该在更改库中的代码后运行测试。如果你更改了测试所描述的行为,测试将不会通过,你将得到指向失败测试的错误。这可能是因为…… -- 你忽略了一些东西,或者你的代码有错误,或者... +- 你忽略了某些内容或代码中有错误,或者…… - 库或测试本身是错误的 -以上两种情况,发生频率更高的是第一个,但第如果二个发生了,可能是边缘情况。 +更频繁发生的是第一种情况,但第二种情况也有发生,在边缘情况下。 -**自动化测试通过之后,你应该做的另一件事是运行 `examples` 文件夹中的示例**。有种情况很少见,但可能会发生:你的更改引入了自动测试未检查的外观差异,注意到这一点的唯一方法是运行示例并让人工发现输出中的差异。如果你不想签出库的两个副本,可以查看[在线例子](https://github.com/tweenjs/tween.js#examples)。 +**自动化测试通过后你应该做的另一件事是运行 `examples` 文件夹中的示例**。这种情况很少见,但可能发生你的更改引入了自动化测试没有检查的外观差异,注意到这一点的唯一方法是运行示例并让人眼发现输出中的差异。如果你不想检出库的两个副本,可以查看[在线示例](https://github.com/tweenjs/tween.js#examples)。 ### 单元测试 -测试用例在 `src/tests.ts` 文件中。 +测试位于 `src/tests.ts` 文件中。 测试使用 [nodeunit](https://www.npmjs.com/package/nodeunit) 执行。 -**TODO:** 如果在浏览器中打开 `test/unit/nodeunit.html`,测试也应该能够正常运行,但是现在已经被损坏。有一个 [打开的问题](https://github.com/tweenjs/tween.js/issues/307) 可以使他们再次工作。 +**TODO:** 如果在浏览器中打开 `test/unit/nodeunit.html`,测试也应该能正常工作,但目前它们已损坏。有一个[未解决的 issue](https://github.com/tweenjs/tween.js/issues/307) 使其重新工作。 ### 代码风格和 lint 测试 -我们使用 [JSCS](http://jscs.info/) 和 [JSHint](http://jshint.com/) 来保证代码风格的统一。 +我们使用 [Prettier](https://prettier.io) 和 [ESLint](https://eslint.org) 来确保代码风格统一。 -要自动格式化代码并报告不可被格式化的代码片段的任何错误,请运行: +要自动格式化代码并报告不能自动格式化的代码片段的任何错误,请运行: -```base +```bash npm run test-lint ``` @@ -102,20 +102,20 @@ Prettier 规则在 `.prettierrc.js` 中,ESLint 规则在 `.eslintrc.js` 中。 ### 其他类型的测试 -我们想回归测试性能,即如果更改使运行变得更慢,或者简单地测试性能,那么我们可以比较不同浏览器之间相同代码的性能。 +我们希望测试性能回归,即更改是否使事情变慢,或者简单地测试性能,这样我们可以比较不同浏览器之间相同代码的性能。 -有一个[open issue](https://github.com/tweenjs/discuss/issues/3)来跟踪这方面的工作,但我们还没有取得进展。请求帮助! :-) +有一个[未解决的 issue](https://github.com/tweenjs/discuss/issues/3) 来跟踪这方面的工作,但我们还没有取得进展。求助!:-) ## 持续集成 -我们使用 GitHub Actions 进行持续集成,以便为每个 pull request 运行构建和测试。 `.github/workflows/tests.yml` 文件告诉 GitHub 要运行什么;在我们的例子中,我们在该文件中指定的操作系统和 Node.js 版本中运行 `npm install`,然后运行 `npm test`。 +我们使用 GitHub Actions 进行持续集成,以便为每个拉取请求运行构建和测试。`.github/workflows/tests.yml` 文件告诉 GitHub 要运行什么;在我们的情况下,我们在该文件中指定的操作系统和 Node.js 版本中运行 `npm install`,然后运行 `npm test`。 -**TODO**:将 macOS 和 Windows 添加到运行测试的操作系统。 请求帮助! :) +**TODO:** 将 macOS 和 Windows 添加到运行测试的操作系统中。求助!:) ## 发布流程 -目前发布过程是手动的。 +目前发布流程是手动的。 -当准备好在 `master` 分支上发布时,确保没有未提交的更改,然后运行 `npm run release:patch` 发布一个新版本,其补丁号已被修改,`npm run release:minor` ,修改 minor 版本号并发布一个新版本,或者 `npm run release:major` 修改 major 版本号并发布一个新版本。 +当准备在 `master` 分支上发布时,确保没有未提交的更改,然后运行 `npm run release:patch` 来发布补丁版本号递增的新版本,运行 `npm run release:minor` 来发布次版本号递增的新版本,或运行 `npm run release:major` 来发布主版本号递增的新版本。 -Tip: 请参阅 [semver.org](https://semver.org/) 和 [npm-semver](https://docs.npmjs.com/misc/semver) 文档以了解语义版本控制。 +提示:请参阅 [semver.org](https://semver.org) 和 [npm-semver](https://docs.npmjs.com/misc/semver) 文档来了解语义版本控制。 \ No newline at end of file diff --git a/docs/user_guide_zh-CN.md b/docs/user_guide_zh-CN.md index c15247d6..812edb73 100644 --- a/docs/user_guide_zh-CN.md +++ b/docs/user_guide_zh-CN.md @@ -1,158 +1,158 @@ -## tween.js 用户指南 +# tween.js 用户指南 更多语言: [English](./user_guide.md), [简体中文](./user_guide_zh-CN.md) -中文用户指南最近更新为 Tween.js v20.0.3 +_**注意** 这是正在进行的工作。如果你发现某些内容不清楚或缺少详细信息,请[提出 issue](https://github.com/tweenjs/tween.js/issues/new)并帮助改进本指南。如果你觉得你也能提供帮助,也可以随时提交你自己的说明或改进!_ -_**NOTE** 这是一个正在进行的工作。 如果你发现某些内容不清楚或缺少详细信息,请 [提出 issue](https://github.com/tweenjs/tween.js/issues/new) 并帮助改进本指南。 或者,如果你觉得自己也能提供帮助,请随时提交你自己的说明或改进!_ +## 什么是补间?它们是如何工作的?为什么要使用它们? -## 什么是 tween ?tween 是如何工作的?为什么要使用 tween ? +补间(来自[_中间帧_](http://en.wikipedia.org/wiki/Inbetweening))是一个概念,允许你以平滑的方式更改对象的属性值。你只需告诉它你想要更改哪些属性,当补间完成运行时它们应该具有什么最终值,以及这应该花费多长时间,补间引擎将负责找到从开始点到结束点的中间值。 -补间(动画)(来自 [in-between](https://en.wikipedia.org/wiki/Inbetweening))是一个概念,允许你以平滑的方式更改对象的属性。你只需告诉它哪些属性要更改,当补间结束运行时它们应该具有哪些最终值,以及这需要多长时间,补间引擎将负责计算从起始点到结束点的值。 +例如,假设你有一个具有 `x` 和 `y` 坐标的 `position` 对象: -例如,`position` 对象拥有 `x` 和 `y` 两个坐标: - -```js +```javascript const position = {x: 100, y: 0} ``` -如果你想将 `x` 坐标的值从 `100` 变成 `200` ,你应该这么做: +如果你想将 `x` 值从 `100` 更改为 `200`,你可以这样做: -```js -// 首先为位置创建一个补间(tween) -const tween = new TWEEN.Tween(position) +```javascript +import {Tween} from '@tweenjs/tween.js' + +// 首先为 position 创建一个补间 +const tween = new Tween(position) -// 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置 +// 然后告诉补间我们想要在 1000 毫秒内对 x 属性进行动画处理 tween.to({x: 200}, 1000) ``` -通常来说这样还不够,tween 已经被创建了,但是它还没被激活(使用),你需要这样启动: +实际上这还不会做任何事情。补间已经创建,但它不是活动的。你需要启动它: -```js -// 启动 +```javascript +// 并将其设置为开始 tween.start() ``` -最后,想要成功的完成这种效果,你需要在主函数中调用 `TWEEN.update` ,如下使用: +最后,为了尽可能平稳地运行,你应该在用于动画的同一主循环中调用 `tween.update()` 函数。这通常看起来像这样: -```js +```javascript animate() function animate() { requestAnimationFrame(animate) // [...] - TWEEN.update() + tween.update() // [...] } ``` -这样在更新每帧的时候都会运行补间动画;经过 1 秒(1000 毫秒)后 `position.x` 将会变成 `200`。 +1 秒后(即 1000 毫秒),`position.x` 将为 `200`。 -除非你在控制台中打印出 `x` 的值,不然你看不到它的变化。你可能想要使用 `onUpdate` 回调: +但除非你将 `x` 的值打印到控制台,否则你看不到它的值变化。你可能想要使用 `onUpdate` 回调: -```js +```javascript tween.onUpdate(function (object) { console.log(object.x) }) ``` -每次更新补间时都会调用此函数; 这种情况发生的频率取决于许多因素——例如,你的计算机或设备的速度有多快(以及有多繁忙!)。 +每次更新补间时都会调用此函数;这种情况发生的频率取决于许多因素——例如,你的计算机或设备有多快(以及有多忙!)。 -到目前为止,我们只使用 tweens 将值打印到控制台,但你可以将它用于 three.js 对象的动画位置之类的事情: +到目前为止,我们只使用补间将值打印到控制台,但你可以将其用于诸如对 three.js 对象的位置进行动画处理之类的事情: -```js -const tween = new TWEEN.Tween(cube.position).to({x: 100, y: 100, z: 100}, 10000).start() +```javascript +const tween = new Tween(cube.position).to({x: 100, y: 100, z: 100}, 10000).start() animate() function animate() { requestAnimationFrame(animate) - TWEEN.update() + tween.update() threeRenderer.render(scene, camera) } ``` -在这种情况下,因为 three.js 渲染器将在渲染之前查看对象的位置,所以不需要使用的 `onUpdate` 回调。 +在这种情况下,由于 three.js 渲染器将在渲染前查看对象的位置,你不需要使用显式的 `onUpdate` 回调。 -你可能也注意到了一些不同的地方:tween.js 可以链式调用! 每个 tween 函数都会返回 tween 实例,所以你可以重写下面的代码: +你可能也注意到这里有些不同:我们在链式调用补间函数!每个补间函数都返回补间实例,所以你可以将以下代码: -```js -const tween = new TWEEN.Tween(position) +```javascript +const tween = new Tween(position) tween.to({x: 200}, 1000) tween.start() ``` -改成这样: +重写为: -```js -const tween = new TWEEN.Tween(position).to({x: 200}, 1000).start() +```javascript +const tween = new Tween(position).to({x: 200}, 1000).start() ``` -在将会看到很多例子,所以熟悉它是很好的!比如 [04-simplest](../examples/04_simplest.html) 这个例子。 +你将在示例中看到很多这种用法,所以熟悉它是好的!查看 [04-simplest](../examples/04_simplest.html) 作为工作示例。 -## tween.js 的动画 +## 使用 tween.js 进行动画 -Tween.js 不会自行运行。你需要显式的调用 `update` 方法来告诉它何时运行。推荐的方法是在主动画循环中执行这个操作。使用 `requestAnimationFrame` 调用此循环以获得最佳的图形性能。 +Tween.js 不会自行运行。你需要通过显式调用每个补间的 `update` 方法或具有多个补间的 `Group` 的 `update` 方法来告诉它何时运行(下面会详细介绍 Groups)。推荐的方法是在你的主动画循环中执行此操作,该循环应使用 `requestAnimationFrame` 调用以获得最佳图形性能: -比如之前这个例子: +我们之前已经看过这个示例: -```js +```javascript animate() function animate() { requestAnimationFrame(animate) // [...] - TWEEN.update() + tween.update() // [...] } ``` -如果不带参数调用,`update` 将会判断当前时间点,以便找出自上次运行以来已经过了多长时间。 +如果不带参数调用,`update` 将确定当前时间,以找出自上次运行以来经过了多长时间。 -当然你也可以传递一个明确的时间参数给 `update` 来更新。因此: +但是你也可以将明确的时间参数传递给 `update`。因此, -```js -TWEEN.update(100) +```javascript +tween.update(100) ``` -意思是“更新时间 = 100 毫秒”。你可以使用它来确保代码中的所有时间相关函数都使用相同的时间值。例如,假设你有一个播放器,并希望同步运行补间。 你的 `animate` 函数可能看起来像这样: +意味着"用时间 = 100 毫秒更新"。你可以使用它来确保代码中的所有时间相关函数都使用完全相同的时间值。例如,假设你有一个播放器并想要同步运行补间。你的 `animate` 代码可能如下所示: -```js -const currentTime = player.currentTime -TWEEN.update(currentTime) +```javascript +let currentTime = player.currentTime +tween.update(currentTime) ``` -我们使用明确的时间值进行单元测试。你可以看下 [tests.ts](../src/tests.ts) 这个例子,看看我们如何用不同的值调用`TWEEN.update()` 来模拟时间传递。 +我们使用明确的时间值进行单元测试。你可以查看 [tests.ts](../src/tests.ts) 来了解我们如何使用不同的值调用 `tween.update()` 来模拟时间流逝。 -## 控制一个补间 +## 控制补间 ### `start` 和 `stop` -到目前为止,我们已经了解了 `Tween.start` 方法,但是还有更多的方法来控制单个补间。也许最重要的一个是 `start` 对应的方法:`stop` 。 如果你想取消一个补间,只要调用这个方法通过一个单独的补间: +到目前为止,我们已经了解了 `Tween.start` 方法,但还有更多方法来控制个别补间。可能最重要的一个是 `start` 的对应方法:`stop`。如果你想取消补间,只需在个别补间上调用此方法: ```js tween.stop() ``` -停止一个从未开始或已经停止的补间没有任何效果。 没有错误被抛出。 +停止从未启动或已经停止的补间没有任何效果。也不会抛出错误。 -`start` 方法还接受一个 `time` 参数。如果你使用它,补间直到那个特定的时刻才会开始;否则它将立即开始(即在下一次调用 `TWEEN.update` 时)。 +`start` 方法还接受 `time` 参数。如果你使用它,补间在那个特定时刻之前不会开始;否则它将尽快开始(即在下一次调用 `tween.update()` 时)。 -`start` 方法接受第二个布尔参数:当为 `true` 时,我们之前使用的补间将从目标对象中的值开始,而不是从头开始。用于停止补间,然后启动另一个将从当前位置继续的补间。 +`start` 方法接受第二个布尔参数:当为 `true` 时,我们之前使用的补间将从目标对象中的值开始,而不是从头开始。对于停止补间然后启动另一个将从当前位置继续的补间很有用。 ### `startFromCurrentValues` -这是 `tween.start(undefined, true)` 的别名,使以前使用的补间从目标对象的最后一个值开始,而不是从头开始。 +这是 `tween.start(undefined, true)` 的别名,使之前使用的 +补间从目标对象的最后值开始,而不是从 +开头开始。 ### `update` -个别补间有一个 `update` 方法。 这实际上是由 `TWEEN.update` 调用的,用于仅使用一个参数构建的补间。 - -在下面的示例中,第二个参数告诉新的 Tween 不要将自己添加到默认组(`TWEEN` 是 `TWEEN.Group` 的一个实例)。如果补间不与组关联(请注意,可以通过将组作为第二个参数传递给构造函数来关联组),则补间需要使用其 `update` 方法手动更新,如下所示: +个别补间有一个 `update` 方法,以便它们可以在动画循环中随时间更新,在每次更新时它们将将更新的值应用到其目标对象。 ```js -const tween = new TWEEN.Tween(someObject, false).to(/*...*/).start() +const tween = new Tween(someObject).to(/*...*/).start() function animate(time) { tween.update(time) @@ -160,198 +160,220 @@ function animate(time) { } ``` -> **Note** 如果你使用 `TWEEN.update()` 作为默认控制所有补间的方式,则无需直接调用 `tween.update()`,但是我们建议你直接如上例所示 [创建自己的补间组](#controlling-groups-of-tweens) 或手动更新补间。 使用组或单独控制的补间的概念很像避免在 JavaScript 代码中使用全局变量的做法:它可以防止一个组件意外破坏其他一些不相关组件的行为。 +### `pause` + +当补间正在运行时(即它已经被 `start` 并且可能已经被 `update` 了多次),它可以被暂停。即使在补间暂停时调用 `update()`,其时间也不会向前移动。`isPlaying` 在补间 `paused` 时仍为 true,其 `update()` 方法继续跟踪时间进度(你可以在补间暂停时继续调用 `update()`)。 + +```js +tween.start() + +function animate() { + tween.update() + requestAnimationFrame(animate) +} +animate() + +// 在补间运行时的任何时候 +tween.pause() +``` ### `chain` -当你按顺序排列不同的补间时,事情会变得更有趣,例如在上一个补间结束的时候立即启动另外一个补间。我们称此为链接补间,它是通过 `chain` 方法完成的。因此,要使 `tweenB` 在 `tweenA` 完成后开始: +当你按顺序排列不同的补间时,事情变得更有趣,即设置一个补间在前一个完成后开始。我们称之为_链式补间_,这通过 `chain` 方法完成。因此,要使 `tweenB` 在 `tweenA` 完成后开始: -```js +```javascript tweenA.chain(tweenB) ``` -或者,可以创造一个无限的链式,`tweenA` 完成时开始 `tweenB`,`tweenB` 完成时开始 `tweenA`: +或者,对于无限链,设置 `tweenA` 在 `tweenB` 完成后开始: -```js +```javascript tweenA.chain(tweenB) tweenB.chain(tweenA) ``` -关于无限的链式查看案例 [Hello world](../examples/00_hello_world.html) 。 +查看 [Hello world](../examples/00_hello_world.html) 来了解这些无限链的示例。 -在其他情况下,你可能希望将多个补间链接到另一个补间,使它们(链接的补间)都同时开始动画: +在其他情况下,你可能希望将多个补间链接到另一个补间,以便它们(链式补间)都同时开始动画: -```js +```javascript tweenA.chain(tweenB, tweenC) ``` -> **Warning** 调用 `tweenA.chain(tweenB)` 实际上修改了 tweenA,所以 tweenB 总是在 tweenA 完成时启动。 `chain` 的返回值只是 tweenA,不是一个新的 tween。 +> **警告** 调用 `tweenA.chain(tweenB)` 实际上修改了 tweenA,因此 tweenB 总是在 tweenA 完成时启动。`chain` 的返回值只是 tweenA,不是新的补间。 ### `repeat` -如果你想让一个补间永远重复,你可以链接到自己,但更好的方法是使用 `repeat` 方法。它接受一个参数,描述第一个补间完成后需要多少次重复: +如果你希望补间永远重复,你可以将其链接到自身,但更好的方法是使用 `repeat` 方法。它接受一个参数,描述在第一个补间完成后你希望有多少次重复: -```js -tween.repeat(10) // 循环10次 -tween.repeat(Infinity) // 无限循环 +```javascript +tween.repeat(10) // 在第一个补间后重复 10 次并停止 +tween.repeat(Infinity) // 永远重复 ``` -补间的总次数将是重复参数加上一个初始补间。查看 [Repeat](../examples/08_repeat.html) 。 +补间的总数将是重复参数加上一个初始补间。 +查看 [Repeat](../examples/08_repeat.html) 示例。 ### `yoyo` -此功能仅在与 `repeat` 一起使用时才有效。 激活时,补间的行为将 _像溜溜球一样_,即它会在开始值和结束值之间来回跳动,而不是仅仅从头开始重复相同的顺序: +此函数只有与 `repeat` 一起使用时才有效。当激活时,补间的行为将_像溜溜球_,即它将在开始值和结束值之间来回跳跃,而不是只是从头开始重复相同的序列: ```js -tween.yoyo(false) // 默认值,动画只会从开始到结束值 -tween.yoyo(true) // tween 将在起始值和结束值之间“yoyo” +tween.yoyo(false) // 默认值,动画只会从开始值到结束值 +tween.yoyo(true) // 补间将在开始值和结束值之间"yoyo" ``` ### `delay` -更复杂的安排可能需要在实际开始运行之前延迟补间。 你可以使用 `delay` 方法来做到这一点: +更复杂的安排可能需要在实际开始运行之前延迟补间。你可以使用 `delay` 方法: -```js +```javascript tween.delay(1000) tween.start() ``` -将在调用 `start` 方法后的 1 秒钟后开始执行。 +将在调用 `start` 方法后 1 秒开始执行。 ### `repeatDelay` -通常,`delay` 时间应用于补间的重复之间,但如果向 `repeatDelay` 函数提供了一个值,则该值将确定补间重复之间经过的总时间。 +通常 `delay` 时间应用于补间的重复之间,但如果为 `repeatDelay` 函数提供了值,则该值将确定补间重复之间经过的总时间。 -参考这个例子: +考虑这个示例: -```js +```javascript tween.delay(1000) tween.repeatDelay(500) tween.start() ``` -补间的第一次迭代将在一秒后发生,第二次迭代将在第一次迭代结束后半秒发生,第三次迭代将在第二次迭代结束后半秒发生,依此类推。如果你想延迟初始迭代但不希望迭代之间有任何延迟,请确保调用 `tween.repeatDelay(0)` 。 +补间的第一次迭代将在一秒后发生,第二次迭代将在第一次迭代结束后半秒发生,第三次迭代将在第二次迭代结束后半秒发生,等等。如果你想延迟初始迭代但不希望迭代之间有任何延迟,请确保调用 `tween.repeatDelay(0)`。 ### `dynamic` -如果 `dynamic` 设置为 `true`(默认为 `false`),则传递给 `tween.to()` 的对象可以在补间动画的外部进行修改。这可用于在运行时动态修改补间的结果。 - -请参阅 [dynamic 示例](http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html)。在那个例子中,在这两个场景中,兔子的位置都在动画期间更新。 兔子的位置恰好是传递给狐狸的 `tween.to()` 方法的对象。 随着兔子位置的更新,在第一个带有 `.dynamic(false)` 的场景中,狐狸向兔子的初始位置移动并且不跟随兔子,而在第二个带有 `.dynamic(true)` 的场景中,狐狸移动到兔子的最终目的地 狐狸因此也被更新,这使得狐狸跟随兔子。 +如果 `dynamic` 设置为 `true`(默认为 `false`),传递给 `tween.to()` 的对象可以在补间动画时从外部修改。这可用于在补间运行时动态修改补间的结果。 -> **Warning** 当 `dynamic` 设置为 `false` 时,Tween 复制传递给 `tween.to()` 的对象并且永远不会修改它(因此从外部更新原始对象不是动态的)。当 `dynamic` 为 `true` 时,Tween 在动画期间使用原始对象作为值的来源(每次更新都读取值,因此可以动态修改它们) **但请注意,在 dynamic 模式下,Tween 将修改传递给 `tween.to()` 的对象的任何插值数组,这可能会对也可能依赖于同一对象的任何外部代码造成副作用。** +查看 [Dynamic to](http://tweenjs.github.io/tween.js/examples/07_dynamic_to.html) 示例。在该示例中,在两个场景中,兔子的位置在动画期间更新。兔子位置恰好是传递给狐狸的 `tween.to()` 方法的对象。随着兔子位置的更新,在第一个带有 `.dynamic(false)` 的场景中,狐狸移动到兔子的初始位置,不追逐兔子,在第二个带有 `.dynamic(true)` 的场景中,狐狸的最终目的地也被更新,这使得狐狸追逐兔子。 -## 控制*所有*补间 +查看其他 `dynamic to` 示例以获得更多想法。 -在 TWEEN 全局对象中可以找到以下方法,除了 `update` 之外,你通常不需要使用其中的大部分方法。 +> **警告** 当 `dynamic` 设置为 `false` 时,Tween 复制传递给 `tween.to()` 的对象且永远不会修改它(因此从外部更新原始对象不是动态的)。当 `dynamic` 为 `true` 时,Tween 在动画期间使用原始对象作为值的来源(每次更新都读取值,因此可以动态修改它们),但请注意**在动态模式下,Tween 将修改传递给 `tween.to()` 的对象的任何插值数组,这可能对也可能依赖于同一对象的任何外部代码造成副作用**。 -### `TWEEN.update(time)` +## 控制补间组 -我们已经讨论过这种方法。它用于更新所有活动的补间。 -如果 `time` 不指定,它将使用当前时间。 +有时你想要一次更新多个补间,当将一组补间分组到应用程序中的逻辑组件时,这可能很有用。你可以使用 `Group` 来做到这一点。 -### `TWEEN.getAll` and `TWEEN.removeAll` +首先将多个补间添加到组中: -用于获取对活动 `tweens` 数组的引用,并分别通过一次调用将它们从数组中移除。 +```js +import {Group, Tween} from '@tweenjs/tween.js' -### `TWEEN.add(tween)` and `TWEEN.remove(tween)` +const tween1 = new Tween(obj1).to(...).start() +const tween2 = new Tween(obj2).to(...).start() -分别用于将补间添加到活动补间列表,或从列表中删除特定补间。 +const group = new Group() +group.add(tween1) +group.add(tween2) +``` -这些方法通常只在内部使用,但如果你想做一些*有趣*的事情,我们会公开这些方法。 +然后在你的动画循环中调用 `group.update()` 而不是在个别补间上: -## 控制补间集 +```js +animate() -使用 `TWEEN` 单例来管理补间可能会导致包含许多组件的大型应用程序出现问题。在这些情况下,你可能想要创建自己的更小的补间集。 +function animate() { + requestAnimationFrame(animate) + // [...] + group.update() + // [...] +} +``` -### 示例:交叉组件冲突 +请注意,补间只能属于单个组。将补间添加到组中会自动将其从任何先前的组中删除。 -如果你有多个组件使用 `TWEEN`,并且每个组件都想管理自己的补间集,则可能会发生冲突。 如果一个组件调用 `TWEEN.update()` 或 `TWEEN.removeAll()`,其他组件的补间也将被更新或删除。 +### `group.getAll()` -### 创建你自己的补间集 +返回添加到组中的所有补间的数组。 -为了解决这个问题,每个组件都可以创建自己的 `TWEEN.Group` 实例(这是全局 `TWEEN` 对象在内部使用的实例)。 在实例化新补间时,这些组可以作为第二个可选参数传入: +### `group.add(tween)` -```js -const groupA = new TWEEN.Group() -const groupB = new TWEEN.Group() +将补间添加到组中。 -const tweenA = new TWEEN.Tween({x: 1}, groupA).to({x: 10}, 100).start() +### `group.remove(tween)` -const tweenB = new TWEEN.Tween({x: 1}, groupB).to({x: 10}, 100).start() +从组中删除补间。 -const tweenC = new TWEEN.Tween({x: 1}).to({x: 10}, 100).start() +### `group.removeAll()` -groupA.update() // 只更新tweenA -groupB.update() // 只更新tweenB -TWEEN.update() // 只更新tweenC +从组中删除所有补间。 -groupA.removeAll() // 只移除tweenA -groupB.removeAll() // 只移除tweenB -TWEEN.removeAll() // 只移除tweenC -``` +### `group.update(time?)` -这样,每个组件都可以处理创建、更新和销毁自己的补间集。 +更新组中的所有补间,带有可选的时间值。如果未提供时间值,则默认为当前时间。 -## 改变缓动功能(别名:让它弹) +## 更改缓动函数(AKA 使其弹跳) -Tween.js 将以线性方式执行值之间的插值(即缓动),因此变化将与经过的时间成正比。 这是可以预见的,但在视觉上也很无趣。 不用担心——可以使用缓动方法轻松更改此行为。 例如: +Tween.js 将以线性方式执行值之间的插值(即缓动),因此变化将与经过的时间成正比。这是可预测的,但在视觉上也相当无趣。不用担心——可以使用 `easing` 方法轻松更改此行为。例如: -```js -tween.easing(TWEEN.Easing.Quadratic.In) +```javascript +import {Tween, Easing} from '@tweenjs/tween.js' +// ... +tween.easing(Easing.Quadratic.In) ``` -这将导致补间缓慢开始向最终值变化,向中间加速,然后快速达到其最终值。 相比之下,`TWEEN.Easing.Quadratic.Out` 将开始向该值快速变化,但在接近最终值时会减慢速度。 +这将导致补间缓慢开始向最终值变化,向中间加速,然后快速达到其最终值。相比之下,`Easing.Quadratic.Out` 会开始快速向值变化,但在接近最终值时会减慢。 + +### 可用的 `Easing` 函数 -### 可用的缓动函数:`TWEEN.Easing` +tween.js 提供了一些现有的缓动函数。它们按照它们代表的方程类型分组:Linear、Quadratic、Cubic、Quartic、Quintic、Sinusoidal、Exponential、Circular、Elastic、Back 和 Bounce,然后按缓动类型:In、Out 和 InOut。 -tween.js 提供了一些现成的缓动功能。它们按照它们表示的方程类型进行分组:线性、二次、三次、四次、五次、正弦、指数、圆形、弹性、后退和反弹,然后按缓动类型:In、Out 和 InOut。 +除非你已经熟悉这些概念,否则名称可能对你没有意义,所以现在可能是查看 [Graphs](../examples/03_graphs.html) 示例的时候了,它在一页中绘制了所有曲线,以便你可以一眼比较它们的外观。 -除非你已经熟悉这些概念,否则这些名称可能对你没有任何意义,所以现在可能是查看 [图表示例](../examples/17_generate_pow.html) 的时候了,该示例在一页中绘制了所有曲线,以便你可以比较它们的动画。 +`Easing` 也有一个名为 `generatePow()` 的函数。此函数根据参数生成不同曲线的缓动函数。你可以在[生成幂缓动的示例](../examples/17_generate_pow.html)页面中查看参数对曲线的相关性。 -这些函数源自 Robert Penner 几年前慷慨地作为免费软件提供的原始方程,但已经过优化后,可以很好地与 JavaScript 配合使用。 +_在应得的地方给予信任:_ 这些函数来自 Robert Penner 几年前慷慨地作为免费软件提供的原始方程集,但已经过优化以与 JavaScript 很好地配合。 -### 使用自定义缓动功能 +### 使用自定义缓动函数 -你不仅可以使用任何现有的缓动函数,还可以提供自己的函数,只要它遵循一些约定即可: +你不仅可以使用任何现有函数,还可以提供自己的函数,只要它遵循几个约定: - 它必须接受一个参数: - - `k`: 缓动过程,或我们的补间所处的时间有多长。允许的值在[0, 1]的范围内。 + - `k`:缓动进度,或我们在补间持续时间中的位置。允许的值在 [0, 1] 范围内。 - 它必须根据输入参数返回一个值。 -无论要更改多少属性,每次更新时每个补间只调用一次缓动函数。 然后将结果与初始值以及此值和最终值之间的差值(_deltas_)一起使用,如以下伪代码所示: +无论要更改多少属性,每次更新时每个补间只调用一次缓动函数。然后将结果与初始值和此值与最终值之间的差值(_增量_)一起使用,如此伪代码所示: -```js +``` easedElapsed = easing(k); for each property: - newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed; + newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed; ``` -对于更注重性能表现的人来说:只有在补间上调用 `start()` 时才会计算 deltas。 +对于性能痴迷的人:只有在补间上调用 `start()` 时才计算增量。 -因此,假设你想要使用自定义缓动函数来缓动值但将 `Math.floor` 应用于输出,因此只会返回整数部分,从而产生一种阶梯式输出: +因此,假设你想要使用一个自定义缓动函数,该函数缓动值但将 Math.floor 应用于输出,因此只返回整数部分,从而产生一种阶梯输出: -```js +```javascript function tenStepEasing(k) { return Math.floor(k * 10) / 10 } ``` -你可以通过简单地调用它的缓动方法在补间中使用它,就像我们之前看到的那样: +你可以通过简单地调用其缓动方法在补间中使用它,就像我们之前看到的: -```js +```javascript tween.easing(tenStepEasing) ``` -查看 [graphs for custom easing functions](../examples/12_graphs_custom_functions.html) 示例,以查看这个动作(还有一些用于生成步进函数的 _metaprogramming_ )。 +查看[自定义缓动函数的图表](../examples/12_graphs_custom_functions.html)示例以查看实际效果(以及一些用于生成步进函数的_元编程_)。 -## 回调函数 +## 回调 -另一个强大的特性是能够在每个补间的生命周期的特定时间运行自己的功能。 当更改属性不够时,通常需要这样做。 +另一个强大的功能是能够在每个补间生命周期中的特定时间运行你自己的函数。当更改属性不够时,通常需要这样做。 -例如,假设你正在试图给一些不能直接访问属性的对象设置动画,但是需要你调用 setter。 你可以使用 `update` 回调来读取新的更新值,然后手动调用 setters。 所有的回调函数都将补间对象作为唯一的参数。 +例如,假设你正在尝试为某个无法直接访问属性但需要你调用 setter 的对象制作动画。你可以使用 `update` 回调来读取新的更新值,然后手动调用 setter。所有回调都以补间对象作为唯一参数传递。 -```js -const trickyObjTween = new TWEEN.Tween({ +```javascript +const trickyObjTween = new Tween({ propertyA: trickyObj.getPropertyA(), propertyB: trickyObj.getPropertyB(), }) @@ -362,60 +384,60 @@ const trickyObjTween = new TWEEN.Tween({ }) ``` -或者假设你想在开始补间时播放声音。 你可以使用 `start` 回调: +或者假设你想在补间开始时播放声音。你可以使用 `start` 回调: -```js -const tween = new TWEEN.Tween(obj).to({x: 100}).onStart(function () { +```javascript +const tween = new Tween(obj).to({x: 100}).onStart(function () { sound.play() }) ``` -每个回调的范围是补间对象——在本例中为 `obj`。 +每个回调的作用域是补间对象——在这种情况下是 `obj`。 ### onStart -在补间开始动画之前执行,在 `delay` 方法指定的任何延迟时间之后。 每个补间只会执行一次,即当补间通过 `repeat()` 重复时不会运行。 +在补间开始动画之前执行,在 `delay` 方法指定的任何延迟时间之后。每个补间只会执行一次,即当补间通过 `repeat()` 重复时_不会_运行。 -`onStart` 非常适合与其他事件同步,或触发需要在补间开始时执行的操作。 +它非常适合与其他事件同步或触发你希望在补间开始时发生的操作。 补间对象作为第一个参数传入。 ### onEveryStart -和 `onStart` 类似,单 `onEveryStart` 在每次重复补间时也会运行。 +与 `onStart` 一样,但它_会_在补间的每次重复时运行。 补间对象作为第一个参数传入。 ### onStop -当补间通过 `stop()` 显式停止时执行,但不会在它正常完成时执行,并且在停止任何可能的链接补间之前执行。 +当补间通过 `stop()` 显式停止时执行,但不会在正常完成时执行,并且在停止任何可能的链式补间之前执行。 补间对象作为第一个参数传入。 ### onUpdate -每次更新补间时执行,在实际更新值之后。 +每次更新补间时执行,在值实际更新之后。 补间对象作为第一个参数传入。 ### onComplete -当补间正常完成(即未停止)时执行。 +当补间正常完成时执行(即未停止)。 补间对象作为第一个参数传入。 ### onRepeat -每当补间刚刚完成一个重复并将开始另一个重复时执行。 +每当补间刚完成一次重复并将开始另一次重复时执行。 补间对象作为第一个参数传入。 -要阐明何时调用 `onStart`、`onEveryStart` 和 `onRepeat`,请参考: +为了澄清何时调用 `onStart`、`onEveryStart` 和 `onRepeat`,请考虑: -```js +```javascript const obj = {x: 0} -const t = new TWEEN.Tween(obj) +const t = new Tween(obj) .to({x: 5}, 5) .repeat(Infinity) .onStart(() => { @@ -431,16 +453,16 @@ const t = new TWEEN.Tween(obj) for (let ticks = 0; ticks < 22; ticks += 1) { console.log('Tick', ticks) - TWEEN.update(ticks) + t.update(ticks) console.log(obj) console.log() } ``` -输出如下所示,左侧如上,右侧带有 `.delay(5)`: +输出看起来像这样,左边如上所示,右边带有 `.delay(5)`: -```txt +``` Tick 0 Tick 0 onStart { x: 0 } onEveryStart @@ -523,40 +545,40 @@ onEveryStart { x: 5 } ### `isPlaying` -开始时为 `true`(即使是暂停)。 +当补间启动时,`tween.isPlaying` 为 `true`,即使它被暂停也是如此。 -当补间停止时,`isPlaying` 和 `isPaused` 都将为 `false`。 +当补间停止时,`isPlaying` 和 `isPaused` 都将为 `false`,因此 `!tween.isPlaying()` 可用于检测补间是否已停止(无论补间是否已完成)。 ### `isPaused` -暂停时为 `true`。 `isPlaying` 也将为 `true`。 如果补间已启动但未暂停,则 `isPlaying` 将为 `true` 而 `isPaused` 将为 `false`。 +当补间被暂停时,`tween.isPaused` 为 `true`。`isPlaying` 也将为 `true`。如果补间已启动但未暂停,`isPlaying` 将为 `true`,`isPaused` 将为 `false`。 ## 高级补间 ### 相对值 -使用 `to` 方法时,也可以使用相对值。 当 tween 启动时,Tween.js 将读取当前属性值并应用相对值来找出新的最终值。 -**但是你需要使用引号**,否则这些值将被视为绝对的。 我们来看一个例子: +当使用 `to` 方法时,你也可以使用相对值。当补间启动时,Tween.js 将读取当前属性值并应用相对值来找出新的最终值。但**你需要使用引号**否则这些值将被视为绝对值。让我们用示例来看这个: -```js +```javascript // 这将使 `x` 属性始终为 100 -const absoluteTween = new TWEEN.Tween(absoluteObj).to({x: 100}) +const absoluteTween = new Tween(absoluteObj).to({x: 100}) // 假设 absoluteObj.x 现在为 0 absoluteTween.start() // 使 x 变为 100 -// 假设 absoluteObj.x 现在是 -100 +// 假设 absoluteObj.x 现在为 -100 absoluteTween.start() // 使 x 变为 100 // 相比之下... -// 这将使 `x` 属性相对于开始时的实际值多 100 个单位 -const relativeTween = new TWEEN.Tween(relativeObj).to({x: '+100'}) +// 这将使 `x` 属性多 100 个单位, +// 相对于它开始时的实际值 +const relativeTween = new Tween(relativeObj).to({x: '+100'}) -// 假设 relativeObj.x 现在是 0 +// 假设 relativeObj.x 现在为 0 relativeTween.start() // 使 x 变为 0 +100 = 100 -// 假设 relativeObj.x 现在是 -100 +// 假设 relativeObj.x 现在为 -100 relativeTween.start() // 使 x 变为 -100 +100 = 0 ``` @@ -564,84 +586,91 @@ relativeTween.start() // 使 x 变为 -100 +100 = 0 ### 补间嵌套对象 -Tween.js 还可以跨嵌套对象更改属性。 例如: +Tween.js 也可以更改跨嵌套对象的属性。例如: -```js +```javascript const nestedObject = {scale: {x: 0, y: 0}, alpha: 0} -const tween = new TWEEN.Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1}) +const tween = new Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1}) ``` -### 补间值的数组 +### 补间到值数组 -除了补间到绝对值或相对值之外,你还可以让 Tween.js 更改一系列值的属性。 为此,你只需为属性指定一个值数组而不是单个值。 例如: +除了补间到绝对值或相对值之外,你还可以让 Tween.js 跨一系列值更改属性。为此,你只需为属性指定值数组而不是单个值。例如: -```js -const tween = new TWEEN.Tween(relativeObj).to({x: [0, -100, 100]}) +```javascript +const tween = new Tween(relativeObj).to({x: [0, -100, 100]}) ``` -将使 `x` 从初始值变为 0,-100 和 100。 +将使 `x` 从其初始值变为 0、-100 和 100。 -这些值的计算方法如下: +计算这些值的方式如下: -- 首先,补间进度如常计算 +- 首先照常计算补间进度 - 进度(从 0 到 1)用作插值函数的输入 -- 基于进度和值的数组,生成内插值 +- 基于进度和值数组,生成插值 -例如,当补间刚刚启动(进度为 0)时,插值函数将返回数组中的第一个值。 当补间到一半时,插值函数将返回一个大约在数组中间的值,当补间结束时,插值函数将返回最后一个值。 +例如,当补间刚开始时(进度为 0),插值函数将返回数组中的第一个值。当补间进行到一半时,插值函数将返回大约在数组中间的值,当补间结束时,插值函数将返回最后一个值。 -你可以使用插值方法更改插值函数。 例如: +你可以通过将 `Interpolation` 函数传递给 +`tween.interpolation` 方法来更改插值模式。例如: -```js -tween.interpolation(TWEEN.Interpolation.Bezier) +```javascript +import {Interpolation} from '@tweenjs/tween.js' +// ... +tween.interpolation(Interpolation.Bezier) ``` 以下值可用: -- TWEEN.Interpolation.Linear -- TWEEN.Interpolation.Bezier -- TWEEN.Interpolation.CatmullRom +- `Interpolation.Linear` +- `Interpolation.Bezier` +- `Interpolation.CatmullRom` -默认是 `Linear`。 +默认为 `Linear`。 -请注意,插值函数对于在同一补间中与数组补间的所有属性都是全局的。 -你不能使用数组和线性函数更改属性 A,也不能使用数组和使用相同补间的贝塞尔函数更改属性 B; 你应该使用两个运行在同一对象上但修改不同属性并使用不同插值函数的补间对象。 +请注意,插值函数对于在同一补间中使用数组补间的所有属性都是全局的。你不能使属性 A 使用数组和 Linear 函数更改,属性 B 使用数组和 Bezier 函数使用同一补间;你应该使用两个在同一对象上运行但修改不同属性并使用不同插值函数的补间对象。 查看 [06_array_interpolation](../examples/06_array_interpolation.html) 示例。 +## 更改"现在"的定义 + +在处理补间时,你不可避免地依赖于对"现在"是什么的定义。默认情况下,Tween.js 使用 performance.now,这是一种可靠且精确的方法。但是,如果你需要调整时间流——例如,减慢时间或为自定义目的操纵时间——你可能会在内部对"现在"的定义与 Tween.js 认为的"现在"之间遇到差异。 + +为了解决这个问题,引入了一个新函数 setNow。此函数允许你重新定义 Tween.js 使用的内部"现在"。你可以将自定义函数传递给 setNow,这将替换默认定义。这提供了更大的灵活性,并能够与你对时间控制的特定要求同步。 + ## 获得最佳性能 -虽然 Tween.js 试图靠自己发挥性能,但没有什么能阻止你以反性能的方式使用它。 以下是一些在使用 Tween.js 时(或通常在 Web 中制作动画时)可以避免拖慢项目速度的方法。 +虽然 Tween.js 试图自己保持高性能,但没有什么能阻止你以反性能的方式使用它。以下是一些在使用 Tween.js 时(或在 Web 中进行动画制作时)避免减慢项目速度的方法。 ### 使用高性能的 CSS -当你尝试为页面中元素的位置设置动画时,最简单的解决方案是为 `top` 和 `left` 样式属性设置动画,如下所示: +当你试图为页面中元素的位置制作动画时,最简单的解决方案是为 `top` 和 `left` 样式属性制作动画,如下所示: -```js +```javascript const element = document.getElementById('myElement') -const tween = new TWEEN.Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) { +const tween = new Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) { element.style.top = object.top + 'px' element.style.left = object.left + 'px' }) ``` -但这确实效率低下,因为更改这些属性会强制浏览器在每次更新时重新计算布局,这是一项非常消耗性能的操作。你应该使用 `transform`,它不会使布局无效,并且在可能的情况下也会进行硬件加速,如下所示: +但这真的效率很低,因为更改这些属性会强制浏览器在每次更新时重新计算布局,这是一个非常昂贵的操作。相反,你应该使用 `transform`,它不会使布局无效,并且在可能的情况下也会进行硬件加速,如下所示: -```js +```javascript const element = document.getElementById('myElement') -const tween = new TWEEN.Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) { - element.style.transform = 'translate(' + object.left + 'px, ' + object.top + 'px);' +const tween = new Tween({top: 0, left: 0}).to({top: 100, left: 100}, 1000).onUpdate(function (object) { + element.style.transform = 'translate(' + object.left + 'px, ' + object.top + 'px)' }) ``` -如果你想了解更多关于高性能的 CSS,看看[这篇文章](https://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/)。 +如果你想了解更多相关信息,请查看[这篇文章](http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/)。 -但是,如果你的动画需求就这么简单,最好只使用 CSS 动画或过渡(在适用的情况下),这样浏览器就可以尽可能地进行优化。 -当你的动画需要涉及复杂的操作时,Tween.js 是非常有用,也就是说,你需要将多个补间同步在一起,在一个完成后开始,循环多次,具有不是使用 CSS 而是使用 Canvas 渲染的图形或 WebGL 等等。 +但是,如果你的动画需求_就是那么_简单,最好只使用 CSS 动画或过渡(在适用的情况下),以便浏览器可以尽可能地优化。当你的动画需求涉及复杂的安排时,Tween.js 最有用,即你需要将多个补间同步在一起,在一个完成后开始一些补间,循环它们多次,有不是用 CSS 而是用 Canvas 或 WebGL 渲染的图形等等。 -### 对垃圾收集器(别名 GC) +### 对垃圾收集器友好(别名 GC) -如果你使用 `onUpdate` 回调,你需要非常小心你放在它上面的东西。 这个函数每秒会被调用很多次,所以如果你在每次更新时都做代价高昂的操作,你可能会阻塞主线程并导致可怕的卡顿,或者——如果你的操作涉及内存分配,你最终会得到 垃圾收集器运行过于频繁,也会导致卡顿。 所以不要做这两件事。 保持你的 `onUpdate` 回调非常轻量级,并确保在开发时也使用内存分析器。 +如果你使用 `onUpdate` 回调,你需要对放入其中的内容非常小心。此函数每秒将被调用多次,因此如果你在每次更新时进行昂贵的操作,你可能会阻塞主线程并导致可怕的_卡顿_,或者——如果你的操作涉及内存分配,你最终会让垃圾收集器运行得太频繁,也会导致_卡顿_。所以不要做这两件事中的任何一件。保持你的 `onUpdate` 回调非常轻量级,并确保在开发时也使用内存分析器。 -### 疯狂的补间 +## 疯狂的补间 -这是你可能不经常使用的东西,但你可以在 Tween.js 之外使用补间方程式。 毕竟,它们只是函数。 因此,你可以使用它们来计算平滑曲线作为输入数据。 例如,它们用于在[此实验](<(http://5013.es/toys/tween.audio/)>)中生成音频数据。 +这是你可能不经常使用的东西,但你可以在 Tween.js 之外使用补间方程。它们毕竟只是函数。因此,你可以使用它们来计算平滑曲线作为输入数据。例如,它们在[这个实验](http://5013.es/toys/tween.audio/)中用于生成音频数据。 \ No newline at end of file