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!如果你觉得自己也能帮上忙的话,也可以提交自己的澄清或改进意见!
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:x
和y
坐标的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) 这将负责更新所有活跃的补间;1秒(即1000毫秒)后,position.x
will be 200
.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 在本例中,由于three.js呈现器将在呈现之前查看对象的位置,因此不需要使用显式onUpdate
callback.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以获取工作示例。
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.update
,update
将确定当前时间,以便找出它距离上次运行的时间有多长。
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()
,以模拟时间的流逝。
start
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
的配对物:stop
。If 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
). Tween
是Tween.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 如果tween与组没有关联(请注意,可以通过将其作为第二个参数传递给构造函数来关联组),则需要使用其updated
method like so: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:tweenB
在tweenA
完成后开始:
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.dynamic
为true
时,补间在动画期间使用原始对象作为值的源(每次更新都读取值,因此可以通过动态调用修改它们),但请注意,在这种模式下,补间将修改传递到Tween.to()
的对象的任何插值数组,这可能会对依赖同一对象的任何外部代码产生副作用。
The following methods are found in the TWEEN global object, and you generally won’t need to use most of them, except for 在TWEEN全局对象中可以找到以下方法,除了update
. 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
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.这些方法通常只在内部使用,但仅在您想做一些有趣的事情时才公开。
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组。
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也将被更新或删除。
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.这样,每个组件都可以处理创建、更新和销毁自己的补间集。
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
将开始朝着值快速变化,但在接近最终值时会减慢。
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。
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:您不仅可以使用任何现有函数,还可以提供自己的函数,只要它遵循两个约定:
k
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函数的元编程)。
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, 每个回调的作用域都是tweened对象,在本例中是obj
.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对象作为第一个参数传入。
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对象作为第一个参数传入。
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。
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})
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。
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上设置动画)时可以避免减慢项目速度的方法。
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:top
和left
样式属性的动画,如下所示:
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渲染的图形,等等。
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
回调非常轻量级,并且在开发过程中一定要使用内存探查器。
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.例如,在这个实验中,它们被用来生成音频数据。