tween.js user guide用户指南

NOTE This is a work in progress. 请注意,这是一项正在进行的工作。If you find that something is unclear or missing details, please file an issue and help make this guide better. 如果您发现某些内容不清楚或缺少详细信息,请提交一个问题并帮助改进本指南。Or feel free to submit clarifications or improvements of your own if you feel you can help too!如果你觉得自己也能帮上忙的话,也可以提交自己的澄清或改进意见!

What is a tween? How do they work? Why do you want to use them?什么是补间?它们是如何工作的?你为什么要用它们?

A tween (from in-between) is a concept that allows you to change the values of the properties of an object in a smooth way. 补间是一个允许您以平滑方式更改对象属性值的概念。You just tell it which properties you want to change, which final values should they have when the tween finishes running, and how long should this take, and the tweening engine will take care of finding the intermediate values from the starting to the ending point. 你只需告诉它你想改变哪些属性,当tween运行结束时它们应该有哪些最终值,以及这需要多长时间,tweening引擎将负责寻找从起点到终点的中间值。For example, suppose you have a position object with x and y coordinates:例如,假设您有一个具有xy坐标的position对象:

var position = {x: 100, y: 0}

If you wanted to change the x value from 100 to 200, you’d do this:如果要将x值从100更改为200,请执行以下操作:

// Create a tween for position first
var tween = new TWEEN.Tween(position)
// Then tell the tween we want to animate the x property over 1000 milliseconds
tween.to({x: 200}, 1000)

Actually this won’t do anything yet. 实际上这还没什么用。The tween has been created but it’s not active. 补间已创建,但未激活。You need to start it:你需要启动它:

// And set it to start
tween.start()

Finally in order to run as smoothly as possible you should call the TWEEN.update function in the same main loop you’re using for animating. 最后,为了尽可能平稳地运行,您应该在用于设置动画的主循环中调用TWEEN.update函数。This generally looks like this:通常如下所示:

animate()
function animate() {
requestAnimationFrame(animate)
// [...]
TWEEN.update()
// [...]
}

This will take care of updating all active tweens; after 1 second (i.e. 1000 milliseconds) position.x will be 200.这将负责更新所有活跃的补间;1秒(即1000毫秒)后,position.x将为200

But unless you print the value of x to the console, you can’t see its value changing. 但是,除非将x的值打印到控制台,否则无法看到其值的变化。You might want to use the onUpdate callback:您可能需要使用onUpdate回调:

tween.onUpdate(function (object) {
console.log(object.x)
})

This function will be called each time the tween is updated; how often this happens depends on many factors–how fast (and how busy!) 每次更新tween时都会调用这个函数;这种情况发生的频率取决于许多因素有多快(和多忙!)your computer or device is, for example.例如,您的计算机或设备是。

So far we’ve only used tweens to print values to the console, but you could use it for things such as animating positions of three.js objects:到目前为止,我们只使用tweens将值打印到控制台,但您可以使用它来设置Three.js对象的位置动画:

var tween = new TWEEN.Tween(cube.position).to({x: 100, y: 100, z: 100}, 10000).start()
animate()
function animate() {
requestAnimationFrame(animate)
TWEEN.update()
threeRenderer.render(scene, camera)
}

In this case, because the three.js renderer will look at the object’s position before rendering, you don’t need to use an explicit onUpdate callback.在本例中,由于three.js呈现器将在呈现之前查看对象的位置,因此不需要使用显式onUpdate回调。

You might have noticed something different here too: we’re chaining the tween function calls! 您可能也注意到了一些不同的地方:我们正在链接tween函数调用!Each tween function returns the tween instance, so you can rewrite the following code:每个tween函数都返回tween实例,因此您可以重写以下代码:

var tween = new TWEEN.Tween(position)
tween.to({x: 200}, 1000)
tween.start()

into this在这里

var tween = new TWEEN.Tween(position).to({x: 200}, 1000).start()

You’ll see this a lot in the examples, so it’s good to be familiar with it! 你会在例子中看到很多,所以熟悉它很好!Check 04-simplest for a working example.请查看04-simplest以获取工作示例。

Animating with tween.js使用tween.js设置动画

Tween.js doesn’t run by itself. Tween.js不是自己运行的。You need to tell it when to run, by explicitly calling the update method. 您需要通过显式调用update方法来告诉它何时运行。The recommended method is to do this inside your main animation loop, which should be called with requestAnimationFrame for getting the best graphics performance:建议的方法是在主动画循环内执行此操作,应使用requestAnimationFrame调用该循环以获得最佳的图形性能:

We’ve seen this example before:我们以前见过这个例子:

animate()
function animate() {
requestAnimationFrame(animate)
// [...]
TWEEN.update()
// [...]
}

If called without parameters, update will determine the current time in order to find out how long has it been since the last time it ran.如果在没有参数的情况下调用updateupdate将确定当前时间,以便找出它距离上次运行的时间有多长。

However you can also pass an explicit time parameter to update. 但是,您也可以传递显式的时间参数进行更新。Thus,因此,

TWEEN.update(100)

means “update with time = 100 milliseconds”. 表示“更新时间=100毫秒”。You can use this to make sure that all the time-dependent functions in your code are using the very same time value. 您可以使用它来确保代码中所有与时间相关的函数都使用相同的时间值。For example, suppose you’ve got a player and want to run tweens in sync. 例如,假设您有一个播放器,并且想要同步运行tweens。Your animate code could look like this:动画代码可以如下所示:

var currentTime = player.currentTime
TWEEN.update(currentTime)

We use explicit time values for the unit tests. 我们对单元测试使用显式时间值。You can have a look at tests.js to see how we call TWEEN.update() with different values in order to simulate time passing.你可以看看tests.js,看看我们如何用不同的值调用TWEEN.update(),以模拟时间的流逝。

Controlling a tween控制补间

start and stop

So far we’ve learnt about the Tween.start method, but there are more methods that control individual tweens. 到目前为止,我们已经了解了Tween.start方法,但是有更多的方法可以控制单个补间。Probably the most important one is the start counterpart: stop. 可能最重要的一个是start的配对物:stopIf you want to cancel a tween, just call this method over an individual tween:如果要取消补间,只需在单个补间上调用此方法:

tween.stop();

Stopping a tween that was never started or that has already been stopped has no effect. 从未开始或已经停止的补间上停止没有效果。No errors are thrown either.也不会抛出错误。

The start method also accepts a time parameter. start方法还接受一个time参数。If you use it, the tween won’t start until that particular moment in time; otherwise it will start as soon as possible (i.e. on the next call to TWEEN.update).如果你用它的话,在那特定的时刻之前,二者之间是不会开始的;否则它将尽快启动(即在下一次调用TWEEN.update时)。

update

Individual tweens have an update method. 每个补间都有一个update方法。This is in fact called by TWEEN.update for tweens that have been constructed with only one argument.这实际上是由TWEEN.update调用的,用于只使用一个参数构造的补间。

In the following example, the second argument tells the new Tween not to add itself to the default group (TWEEN is an instance of TWEEN.Group). 在下面的示例中,第二个参数告诉新补间不要将自己添加到默认组(TweenTween.group的实例)。If the tween is not associated with a group (note that a group can be associated by passing it in as the second arg to the constructor), then the tween needs to be updated manually using its updated method like so:如果tween与组没有关联(请注意,可以通过将其作为第二个参数传递给构造函数来关联组),则需要使用其updated方法手动更新补间,如下所示:

const tween = new TWEEN.Tween(someObject, false).to(/*...*/).start()
function animate(time) {
tween.update(time)
requestAnimationFrame(animate)
}

IMPORTANT! You don’t need to call tween.update() directly if you’re using TWEEN.update() as a way to control all tweens by default, however we recommend that you either make your own groups of tweens or manually update your tweens directly as in the last example. 重要!如果默认情况下使用tween.update()控制所有补间,则不需要直接调用tween.update(),但是我们建议您创建自己的补间组,或者像上一个示例中那样直接手动更新补间。The concept of using groups or individually-controlled tweens is much like the practice of avoiding use of global variables in your JavaScript code: it prevents one component from accidentally ruining the behavior of some other unrelated component.使用组或单独控制的tween的概念非常类似于避免在JavaScript代码中使用全局变量的实践:它可以防止一个组件意外地破坏其他不相关组件的行为。

Using TWEEN to control your tweens is like using globals: and it is only good for simple cases (f.e. small demos, prototypes, etc) but it may not scale well for big apps that may have different parts that need to animate tweens on differing schedules.使用TWEEN来控制补间就像使用globals一样:它只适用于简单的情况(例如小型演示、原型等),但对于那些可能有不同部分需要在不同的时间表上为TWEEN设置动画的大型应用程序,它可能无法很好地扩展。

chain

Things get more interesting when you sequence different tweens in order, i.e. setup one tween to start once a previous one has finished. 当你按顺序排列不同的补间时,事情会变得更有趣,即设置一个补间在前一个补间完成后开始。We call this chaining tweens, and it’s done with the chain method. 我们称之为连缀补间,它是用连缀方法完成的。Thus, to make tweenB start after tweenA finishes:因此,要使tweenBtweenA完成后开始:

tweenA.chain(tweenB)

Or, for an infinite chain, set tweenA to start once tweenB finishes:或者,对于无限连缀,将tweenA设置为tweenB完成后开始:

tweenA.chain(tweenB)
tweenB.chain(tweenA)

Check Hello world to see an example of these infinite chains.查看helloworld以查看这些无限连缀的示例。

In other cases, you may want to chain multiple tweens to another tween in a way that they (the chained tweens) all start animating at the same time:在其他情况下,您可能希望将多个补间链接到另一个补间,使它们(连缀的补间)同时开始设置动画:

tweenA.chain(tweenB, tweenC)

WARNING: Calling tweenA.chain(tweenB) actually modifies tweenA so that tweenB is always started when tweenA finishes. 警告:调用tweenA.chain(tweenB)实际上会修改tweenA,这样tweenA完成时,tweenB总是启动的。The return value of chain is just tweenA, not a new tween.链的返回值只是tweenA,而不是一个新补间。

repeat

If you wanted a tween to repeat forever you could chain it to itself, but a better way is to use the repeat method. 如果你想让一个补间永远重复,你可以将它链接到它本身,但是更好的方法是使用repeat方法。It accepts a parameter that describes how many repetitions you want after the first tween is completed:它接受一个参数,该参数描述在完成第一个补间之后要重复多少次:

tween.repeat(10) // repeats 10 times after the first tween and stops
tween.repeat(Infinity) // repeats forever

The total number of tweens will be the repeat parameter plus one for the initial tween.补间的总数将是repeat参数加上一个初始补间。Check the Repeat example.请请查看重复示例。

yoyo

This function only has effect if used along with repeat. 此函数只有与repeat一起使用时才有效。When active, the behaviour of the tween will be like a yoyo, i.e. it will bounce to and from the start and end values, instead of just repeating the same sequence from the beginning.当它处于活动状态时,补间的行为就像一个悠悠球,也就是说,它会在开始值和结束值之间来回跳动,而不是从一开始就重复同样的顺序。

delay

More complex arrangements might require delaying a tween before it actually starts running. 更复杂的安排可能需要在补间真正开始运行之前延迟它。You can do that using the delay method:您可以使用delay方法:

tween.delay(1000)
tween.start()

will start executing 1 second after the start method has been called.将在调用start方法后1秒开始执行。

repeatDelay

Normally the delay time is applied between repetitions of a tween, but if a value is provided to the repeatDelay function then that value will determine the total time elapsed between repetitions of a tween.通常情况下,delay时间在两次补间重复之间应用,但如果向repeatDelay函数提供一个值,则该值将确定两次补间重复之间经过的总时间。

Consider this example:

tween.delay(1000)
tween.repeatDelay(500)
tween.start()

The first iteration of the tween will happen after one second, the second iteration will happen a half second after the first iteration ends, the third iteration will happen a half second after the second iteration ends, etc. 补间的第一次迭代将在1秒后发生,第二次迭代将在第一次迭代结束后半秒发生,第三次迭代将在第二次迭代结束后半秒发生,等等。If you want to delay the initial iteration but you don’t want any delay between iterations, then make sure to call tween.repeatDelay(0).如果要延迟初始迭代,但不希望在迭代之间有任何延迟,那么请确保调用tween.repeatDelay(0)

dynamic

If dynamic is set to true (it defaults to false) objects passed to tween.to() can be modified on the outside of a tween while the tween is animating. 如果将dynamic设置为true(默认为false),则传递给补间的对象可以在补间设置动画时在补间的外部进行修改。This can be used to dynamically modify the outcome of a tween while it is running.这可用于在补间运行时动态修改其结果。

See the Dynamic to example. 请参见动态到示例。In that example, in both scenes, the position of the rabbit is updated during the animation. 在该示例中,在两个场景中,兔子的位置都在动画期间更新。The rabbit position happens to be the object passed into the fox’s tween.to() method. 兔子位置恰好是传递到狐狸的tween.to()方法中的对象。As the rabbit position is updated, in the first scene with .dynamic(false) the fox moves towards the initial position of the rabbit and does not chase the rabbit, and in the second scene with .dynamic(true) the final destination of the fox is hence also updated which makes the fox chase the rabbit.随着兔子位置的更新,在第一个场景中使用.dynamic(false)时,狐狸会朝兔子的初始位置移动,而不会追逐兔子;在第二个场景中使用.dynamic(true)时,狐狸的最终目的地也会随之更新,从而使狐狸追逐兔子。

See the other dynamic to examples for more ideas.有关更多想法,请参阅其他动态示例。

IMPORTANT! When dynamic is set to false, Tween makes a copy of the object passed into tween.to() and will never modify it (hence updating the original object from the outside is not dynamic. 重要!dynamic设置为false时,补间会将对象的副本传递到Tween.to()中,并且永远不会修改它(因此从外部更新原始对象不是动态的)。When dynamic is true, Tween uses the original object as the source of values during animation (every update reads the values, hence they can be modified dynamicall) but note that in this mode, Tween will modify any interpolation arrays of the object passed into tween.to() which may cause side-effects on any external code that may also rely on the same object.dynamictrue时,补间在动画期间使用原始对象作为值的源(每次更新都读取值,因此可以通过动态调用修改它们),但请注意,在这种模式下,补间将修改传递到Tween.to()的对象的任何插值数组,这可能会对依赖同一对象的任何外部代码产生副作用。

Controlling all the tweens控制所有补间

The following methods are found in the TWEEN global object, and you generally won’t need to use most of them, except for update. 在TWEEN全局对象中可以找到以下方法,除了update之外,您通常不需要使用大多数方法。TWEEN is effectively an instance of TWEEN.Group, and by default all new Tweens are associated to this global Group unless otherwise specified (see the next section on grouping tweens with your own Groups).TWEEN实际上是TWEEN.Group的一个实例,默认情况下,除非另有指定,否则所有新TWEEN都与这个全局组相关联(请参阅下一节关于将补间与您自己的组分组的内容)。

TWEEN.update(time)

We’ve already talked about this method. 我们已经讨论过这个方法了。It is used to update all the active tweens.它用于更新所有活动的补间。

If time is not specified, it will use the current time.如果没有指定time,它将使用当前时间。

TWEEN.getAll and TWEEN.removeAll

Used to get a reference to the active tweens array and to remove all of them from the array with just one call, respectively.用于获取对活动tweens数组的引用,并分别通过一个调用将它们从数组中移除。

TWEEN.add(tween) and TWEEN.remove(tween)

Used to add a tween to the list of active tweens, or to remove a specific one from the list, respectively.分别用于将补间添加到活动补间列表或从列表中移除特定补间。

These methods are usually used internally only, but are exposed just in case you want to do something funny.这些方法通常只在内部使用,但仅在您想做一些有趣的事情时才公开。

Controlling groups of tweens控制补间组

Using the TWEEN singleton to manage your tweens can cause issues in large apps with many components. 使用TWEEN singleton来管理TWEEN可能会导致具有许多组件的大型应用程序出现问题。In these cases, you may want to create your own smaller groups of tweens.在这些情况下,您可能需要创建自己的较小的tweens组。

Example: cross-component conflict示例:跨组件冲突

A conflict can occur if you have multiple components using TWEEN, and each component wants to manage its own set of tweens. 如果您有多个使用TWEEN的组件,并且每个组件都希望管理自己的TWEEN集,则可能会发生冲突。If one component calls TWEEN.update() or TWEEN.removeAll() the tweens of other components will also be updated or removed.如果一个组件调用TWEEN.update()TWEEN.removeAll(),那么其他组件的TWEEN也将被更新或删除。

Creating your own tween groups创建自己的补间组

To solve this, each component can make their own instance of TWEEN.Group (which is what the global TWEEN object uses internally). 为了解决这个问题,每个组件都可以创建自己的TWEEN.Group实例(这是全局TWEEN对象在内部使用的)。These groups can be passed in as a second optional parameter when instantiating a new tween:在实例化新的补间时,这些组可以作为第二个可选参数传入:

var groupA = new TWEEN.Group()
var groupB = new TWEEN.Group()
var tweenA = new TWEEN.Tween({x: 1}, groupA).to({x: 10}, 100).start()
var tweenB = new TWEEN.Tween({x: 1}, groupB).to({x: 10}, 100).start()
var tweenC = new TWEEN.Tween({x: 1}).to({x: 10}, 100).start()
groupA.update() // only updates tweenA
groupB.update() // only updates tweenB
TWEEN.update() // only updates tweenC
groupA.removeAll() // only removes tweenA
groupB.removeAll() // only removes tweenB
TWEEN.removeAll() // only removes tweenC

In this way, each component can handle creating, updating, and destroying its own set of tweens.这样,每个组件都可以处理创建、更新和销毁自己的补间集。

Changing the easing function (AKA make it bouncy)改变缓动功能(又名使其有弹性)

Tween.js will perform the interpolation between values (i.e. the easing) in a linear manner, so the change will be directly proportional to the elapsed time. Tween.js将以线性方式执行值之间的插值(即缓动),因此变化将与经过的时间成正比。This is predictable but also quite uninteresting visually wise. 这是可以预见的,但在视觉上也相当乏味。Worry not–this behaviour can be easily changed using the easing method. 不用担心,使用easing方法可以很容易地改变这种行为。For example:例如:

tween.easing(TWEEN.Easing.Quadratic.In)

This will result in the tween slowly starting to change towards the final value, accelerating towards the middle, and then quickly reaching its final value. 这将导致补间慢慢开始向最终值变化,向中间加速,然后迅速达到最终值。In contrast, TWEEN.Easing.Quadratic.Out would start changing quickly towards the value, but then slow down as it approaches the final value.相比之下,TWEEN.Easing.Quadratic.Out将开始朝着值快速变化,但在接近最终值时会减慢。

Available easing functions: 可用的缓动函数:TWEEN.Easing

There are a few existing easing functions provided with tween.js. tween.js提供了一些现有的放松功能。They are grouped by the type of equation they represent: Linear, Quadratic, Cubic, Quartic, Quintic, Sinusoidal, Exponential, Circular, Elastic, Back and Bounce, and then by the easing type: In, Out and InOut.它们按所代表的方程类型分组:线性、二次、三次、四次、五次、正弦、指数、圆形、弹性、回弹和反弹,然后按放松类型分组:输入、输出和输入。

Probably the names won’t be saying anything to you unless you’re familiar with these concepts already, so it is probably the time to check the Graphs example, which graphs all the curves in one page so you can compare how they look at a glance.除非您已经熟悉这些概念,否则这些名称可能不会对您有任何意义,因此现在可能是请查看Graphs示例的时候了,该示例将所有曲线绘制在一个页面中,以便您可以比较它们的外观。

Credit where credit is due: these functions are derived from the original set of equations that Robert Penner graciously made available as free software a few years ago, but have been optimised to play nicely with JavaScript.值得称赞的地方:这些函数是从Robert Penner几年前作为免费软件提供的原始方程组派生出来的,但是经过优化,可以很好地使用JavaScript。

Using a custom easing function使用自定义缓动函数

Not only can you use any of the existing functions, but you can also provide your own, as long as it follows a couple of conventions:您不仅可以使用任何现有函数,还可以提供自己的函数,只要它遵循两个约定:

The easing function is only called once per tween on each update, no matter how many properties are to be changed. 每次更新时,每次补间只调用一次缓动函数,不管要更改多少属性。The result is then used with the initial value and the difference (the deltas) between this and the final values, as in this pseudocode:然后将结果与初始值以及该值与最终值之间的差值(增量)一起使用,如以下伪代码所示:

easedElapsed = easing(k);
for each property:
newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed;

For the performance-obsessed people out there: the deltas are calculated only when start() is called on a tween.对于那些对性能痴迷的人来说:只有在补间上调用start()时才会计算增量。

So let’s suppose you wanted to use a custom easing function that eased the values but applied a Math.floor to the output, so only the integer part would be returned, resulting in a sort of step-ladder output:因此,假设您想使用一个自定义的缓动函数,该函数缓和了值,但对输出应用了Math.floor,因此只返回整数部分,从而产生一种阶梯式输出:

function tenStepEasing(k) {
return Math.floor(k * 10) / 10
}

And you could use it in a tween by simply calling its easing method, as we’ve seen before:你可以在补间中使用它,只需调用它的缓动方法,就像我们之前看到的:

tween.easing(tenStepEasing)

Check the graphs for custom easing functions example to see this in action (and also some metaprogramming for generating step functions).请查看自定义函数示例的图形以了解这一点(以及一些用于生成step函数的元编程)。

Callbacks回调

Another powerful feature is to be able to run your own functions at specific times in each tween’s life cycle. 另一个强大的特性是能够在每个tween生命周期的特定时间运行自己的函数。This is usually required when changing properties is not enough.当更改属性还不够时,通常需要这样做。

For example, suppose you’re trying to animate some object whose properties can’t be accessed directly but require you to call a setter instead. You can use an update callback to read the new updated values and then manually call the setters. All callbacks are passed the tweened object as the only parameter.

var trickyObjTween = new TWEEN.Tween({
propertyA: trickyObj.getPropertyA(),
propertyB: trickyObj.getPropertyB(),
})
.to({propertyA: 100, propertyB: 200})
.onUpdate(function (object) {
object.setA(object.propertyA)
object.setB(object.propertyB)
})

Or imagine you want to play a sound when a tween is started. 或者想象一下,当一个补间启动时,你想播放一个声音。You can use a start callback:您可以使用start回调:

var tween = new TWEEN.Tween(obj).to({x: 100}).onStart(function () {
sound.play()
})

The scope for each callback is the tweened object–in this case, obj.每个回调的作用域都是tweened对象,在本例中是obj

onStart

Executed right before the tween starts animating, after any delay time specified by the delay method. 在补间开始设置动画之前,在delay方法指定的任何延迟时间之后执行。This will be executed only once per tween, i.e. it will not be run when the tween is repeated via repeat().每个补间只执行一次,即通过repeat()重复补间时不会运行。

It is great for synchronising to other events or triggering actions you want to happen when a tween starts.这是伟大的同步到其他事件或触发行动,你想发生的时候,一个补间开始。

The tweened object is passed in as the first parameter.tweened对象作为第一个参数传入。

onStop

Executed when a tween is explicitly stopped via stop(), but not when it is completed normally, and before stopping any possible chained tween.在通过stop()显式停止补间时执行,但在正常完成时以及在停止任何可能的连缀补间之前不执行。

The tweened object is passed in as the first parameter.tweened对象作为第一个参数传入。

onUpdate更新

Executed each time the tween is updated, after the values have been actually updated.每次更新tween时,在实际更新值之后执行。

The tweened object is passed in as the first parameter.tweened对象作为第一个参数传入。

onComplete

Executed when a tween is finished normally (i.e. not stopped).在补间正常结束(即未停止)时执行。

The tweened object is passed in as the first parameter.tweened对象作为第一个参数传入。

onRepeat

Executed whenever a tween has just finished one repetition and will begin another.每当一个补间刚刚完成一次重复,并将开始另一次重复时执行。

The tweened object is passed in as the first parameter.tweened对象作为第一个参数传入。

Advanced tweening高级补间

Relative values相对值

You can also use relative values when using the to method. 在使用to方法时,也可以使用相对值。When the tween is started, Tween.js will read the current property values and apply the relative values to find out the new final values. 当补间启动时,tween.js将读取当前属性值并应用相对值来找出新的最终值。But you need to use quotes or the values will be taken as absolute. 但您需要使用引号,否则这些值将被视为绝对值。Let’s see this with an example:让我们用一个例子来看看:

// This will make the `x` property be 100, always
var absoluteTween = new TWEEN.Tween(absoluteObj).to({x: 100})
// Suppose absoluteObj.x is 0 now
absoluteTween.start() // Makes x go to 100
// Suppose absoluteObj.x is -100 now
absoluteTween.start() // Makes x go to 100
// In contrast...
// This will make the `x` property be 100 units more,
// relative to the actual value when it starts
var relativeTween = new TWEEN.Tween(relativeObj).to({x: '+100'})
// Suppose relativeObj.x is 0 now
relativeTween.start() // Makes x go to 0 +100 = 100
// Suppose relativeObj.x is -100 now
relativeTween.start() // Makes x go to -100 +100 = 0

Check 09_relative_values for an example.例如,请查看09_relative_values

Tweening nested objects补间嵌套对象

Tween.js can also change properties across nested objects. Tween.js还可以跨嵌套对象更改属性。For example:例如:

var nestedObject = {scale: {x: 0, y: 0}, alpha: 0}
var tween = new TWEEN.Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1})

Tweening to arrays of values补间为值数组

In addition to tweening to an absolute or a relative value, you can also have Tween.js change properties across a series of values. 除了补间为绝对值或相对值外,还可以跨一系列值更改Tween.js属性。To do this, you just need to specify an array of values instead of a single value for a property. 为此,只需为属性指定一个值数组,而不是单个值。For example:例如:

var tween = new TWEEN.Tween(relativeObj).to({x: [0, -100, 100]})

will make x go from its initial value to 0, -100 and 100.将使x从初始值变为0、-100和100。

The way these values are calculated is as follows:计算这些值的方法如下:

For example, when the tween has just started (progress is 0), the interpolation function will return the first value in the array. 例如,当tween刚刚开始(progress为0)时,插值函数将返回数组中的第一个值。When the tween is halfway, the interpolation function will return a value approximately in the middle of the array, and when the tween is at the end, the interpolation function will return the last value.当补间中途,插值函数将返回一个近似于数组中间的值,当补间在结尾时,插值函数将返回最后一个值。

You can change the interpolation function with the interpolation method. 可以使用interpolation方法更改插值函数。For example:例如:

tween.interpolation(TWEEN.Interpolation.Bezier)

The following values are available:以下值可用:

The default is Linear.默认值为Linear

Note that the interpolation function is global to all properties that are tweened with arrays in the same tween. 请注意,插值函数对于使用同一补间中的数组补间的所有属性都是全局的。You can’t make property A change with an array and a Linear function, and property B with an array too and a Bezier function using the same tween; you should use two tween objects running over the same object but modifying different properties and using different interpolation functions.不能用数组和线性函数更改属性A,也不能用数组和贝塞尔函数更改属性B;应该使用两个在同一对象上运行但修改不同特性和使用不同插值函数的tween对象。

Check 06_array_interpolation for an example.例如,请查看06_array_interpolation

Getting the best performance获得最佳性能

While Tween.js tries to be performant on its own, nothing prevents you from using it in a way that is counterperformant. 当Tween.js试图独立运行时,没有什么能阻止您以一种与之相反的方式使用它。Here are some of the ways you can avoid slowing down your projects when using Tween.js (or when animating in the web, in general).下面是一些在使用Tween.js(或者通常在web上设置动画)时可以避免减慢项目速度的方法。

Use performant CSS使用性能CSS

When you try to animate the position of an element in the page, the easiest solution is to animate the top and left style properties, like this:当您尝试设置元素在页面中位置的动画时,最简单的解决方案是设置topleft样式属性的动画,如下所示:

var element = document.getElementById('myElement')
var tween = new TWEEN.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'
})

but this is really inefficient because altering these properties forces the browser to recalculate the layout on each update, and this is a very costly operation. 但这确实是低效的,因为更改这些属性会迫使浏览器在每次更新时重新计算布局,这是一个非常昂贵的操作。Instead of using these, you should use transform, which doesn’t invalidate the layout and will also be hardware accelerated when possible, like this:您应该使用transform,而不是使用这些,transform不会使布局无效,并且在可能的情况下还将进行硬件加速,如下所示:

var element = document.getElementById('myElement')
var 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)'
})

If you want to read more about this, have a look at this article.如果你想读更多关于这方面的内容,请看这篇文章

However, if your animation needs are that simple, it might be better to just use CSS animations or transitions, where applicable, so that the browser can optimise as much as possible. 但是,如果您的动画需求如此简单,那么最好只使用CSS动画或过渡(如果适用),这样浏览器就可以尽可能地优化。Tween.js is most useful when your animation needs involve complex arrangements, i.e. you need to sync several tweens together, have some start after one has finished, loop them a number of times, have graphics that are not rendered with CSS but with Canvas or WebGL, etc.当您的动画需要涉及复杂的安排时,Tween.js最有用,即您需要将多个Tween同步在一起,在一个Tween完成后有一些开始,多次循环它们,具有不是用CSS而是用Canvas或WebGL渲染的图形,等等。

Be good to the Garbage collector (alias the GC)善待垃圾收集器(别名GC)

If you use an onUpdate callback, you need to be very careful with what you put on it. 如果您使用onUpdate回调,那么您需要非常小心地放置在它上面的内容。This function will be called many times per second, so if you’re doing costly operations on each update, you might block the main thread and cause horrible jank, or—if your operations involve memory allocations, you’ll end up getting the garbage collector to run too often, and cause jank too. 这个函数每秒会被调用很多次,因此如果每次更新都要执行代价高昂的操作,则可能会阻塞主线程并导致严重的jank,或者如果操作涉及内存分配,则最终会导致垃圾收集器过于频繁地运行,并导致jank。So just don’t do either of those things. Keep your onUpdate callbacks very lightweight, and be sure to also use a memory profiler while you’re developing.所以不要做这两件事。保持onUpdate回调非常轻量级,并且在开发过程中一定要使用内存探查器。

Crazy tweening疯狂的补间

This is something you might not use often, but you can use the tweening equations outside of Tween.js. 这是您可能不经常使用的,但是您可以在Tween.js之外使用补间公式。They’re just functions, after all. 毕竟,它们只是函数。So you could use them to calculate smooth curves as input data. 所以你可以用它们来计算平滑曲线作为输入数据。For example, they’re used to generate audio data in this experiment.例如,在这个实验中,它们被用来生成音频数据。