Tweenjs使用指南(翻译)
前面学到了tween.js
,但是网上的文档有点不全,为了学习英语我把双语版的放上来:
英文版文档地址:tween.js文档
# What is a tween? How do they work? Why do you want to use them?什么是补间?它是如何工作的?你为什么要使用它们
A tween 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. For example, suppose you have a position object with x and y coordinates:
补间是一个允许您以一种平滑的方式更改对象属性值的概念。你只需要告诉它你想改变哪些属性,当补间结束运行时,它们应该是哪些最终值,并且可以定义发生这个过程需要多长时间,tween
引擎会负责寻找从起点到终点的中间值。例如:假设你有一个具有x和y坐标的位置对象:
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
//首先传入position创建一个补间
var tween = new TWEEN.Tween(position)
// Then tell the tween we want to animate the x property over 1000 milliseconds
//然后告诉补间我们想在1000毫秒以内变动这个x属性
tween.to({x: 200}, 1000)
2
3
4
5
6
7
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()
2
3
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. This generally looks like this:
最后,为了能够尽量平滑的实现动画,你应该在动画的主循环中调用TWEEN.update
函数:
animate()
function animate() {
requestAnimationFrame(animate)
// [...]
TWEEN.update()
// [...]
}
2
3
4
5
6
7
8
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. You might want to use the onUpdate callback:
但是除非你把x的值打印到控制台, 你都看不到它的值在变化。您可能需要使用onUpdate
回调:
tween.onUpdate(function (object) {
console.log(object.x)
})
2
3
This function will be called each time the tween is updated; how often this happens depends on many factors--how fast (and how busy!) 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)
}
2
3
4
5
6
7
8
9
10
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! Each tween function returns the tween instance, so you can rewrite the following code:
你可能也注意到了这里的不同:tween
函数我们是链式调用的!每个tween
的函数返回该tween
的实例,因此您可以重写以下代码:
var tween = new TWEEN.Tween(position)
tween.to({x: 200}, 1000)
tween.start()
2
3
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. You need to tell it when to run, by explicitly calling the update method. The recommended method is to do this inside your main animation loop, which should be called with requestAnimationFrame for getting the best graphics performance:
We've seen this example before:
Tween.js
不会自己运行。你得通过显示调用update
方法告诉它什么时候运行。推荐的方法是在主动画循环中执行此操作,比如在requestAnimationFrame中调用以获得最好的图形性能:
我们以前见过这个例子:
animate()
function animate() {
requestAnimationFrame(animate)
// [...]
TWEEN.update()
// [...]
}
2
3
4
5
6
7
8
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.
However you can also pass an explicit time parameter to update. Thus,
如果调用的时候没有参数,update
将确定当前时间,以确定从上次运行到现在经过多长时间。
但是,你也可以传递一个显式的时间参数给update
。例如:
TWEEN.update(100)
means "update with time = 100 milliseconds". 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. Your animate code could look like this:
意思是 "更新时间 = 100毫秒”。您可以使用它来确保代码中所有依赖于时间的函数都使用相同的时间值。例如,假设你有一个播放器,想要同步运行补间。你的动画代码看起来像这样:
var currentTime = player.currentTime
TWEEN.update(currentTime)
2
# Controlling a tween 控制tween
# start
and stop
So far we've learnt about the Tween.start method, but there are more methods that control individual tweens. Probably the most important one is the start counterpart: stop. If you want to cancel a tween, just call this method over an individual tween:
目前为止,我们学习了Tween.start
方法,但是还有更多方法可以控制单个补间。可能最重要的一个是和start
对应的stop
。如果你想取消一个补间,只需在单个补间上调用此方法:
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. 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).
停止一个从未开始或已经停止的补间是没有效果的。不过也不会抛出错误。
start
方法还接受一个time
参数。如果你使用它,补间直到那个特定的时刻才会开始;否则它会尽快启动(即在下一次调用TWEEN.update
时)。
# update
Individual tweens also have an update method---this is in fact called by TWEEN.update. You generally don't need to call this directly, but might be useful if you're doing crazy hacks.
单个补间还有一个update
方法 -- 这实际上是由TWEEN.update
调用的。您通常不需要直接调用它,但如果您正在进行疯狂的修改,它可能会很有用。
# 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:
当你将不同的补间按顺序排列时,事情会变得更有趣,例如,设置一个补间在前一个补间完成后开始。我们称之为链式补间,这是用chain
方法完成的。因此,让补间B在补间A结束后开始:
tweenA.chain(tweenB)
Or, for an infinite chain, set tweenA to start once tweenB finishes:
或者,设置一个没有止境的链,在补间B结束时设置补间A开始:
tweenA.chain(tweenB)
tweenB.chain(tweenA)
2
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. The return value of chain is just tweenA, not a new tween.
调用tweenA.chain(tweenB)
实际上修改了tweenA
,这样当tweenA
结束时,tweenB
总是启动。chain
的返回值只是tweenA
,而不是一个新的tween
# 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. It accepts a parameter that describes how many repetitions you want after the first tween is completed:
如果你想让补间永远重复,你可以把使用chain
把它自己连起来,但更好的方法是使用repeat
方法。它接受一个参数,用于描述第一个补间完成后需要重复的次数:
tween.repeat(10) // repeats 10 times after the first tween and stops 第一次动画结束后重复10次
tween.repeat(Infinity) // repeats forever 永远重复
2
The total number of tweens will be the repeat parameter plus one for the initial tween.
补间的总数将是repeat
参数加上初始补间的1。
# yoyo
This function only has effect if used along with 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:
此功能只有在和repeat
使用时才有效。当激活时,补间的行为就像溜溜球,也就是说,它将从开始值和结束值来回弹跳,而不是一开始就重复相同的顺序:
tween.yoyo(false) // default value, animation will only go from start to end value 默认值,动画只会从开始到结束的值
tween.yoyo(true) // tween will 'yoyo' between start and end values 补间会在起始值和结束值之间“yoyo”
2
# 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()
2
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.
Consider this example:
通常情况下,delay
时间是在补间重复之间,但是如果为repeatDelay
函数提供了一个值,那么这个值将决定补间重复之间经过的总时间。
考虑一下这个例子:
tween.delay(1000)
tween.repeatDelay(500)
tween.start()
2
3
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. 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)
。
# 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.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.
我们已经讨论过这个方法。它被用来更新所有活跃的补间。 如果未指定时间,则使用当前时间。
# 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. In these cases, you may want to create your own smaller groups of tweens.
在有很多组件的大型应用中,使用TWEEN
单例来管理补间可能会导致问题。在这些情况下,您可能希望创建自己的较小的补间组。
# 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. If one component calls TWEEN.update() or TWEEN.removeAll() the tweens of other components will also be updated or removed.
如果有多个使用TWEEN
的组件,可能会发生冲突,每个组件都想管理自己的补间集合。如果一个组件调用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). These groups can be passed in as a second optional parameter when instantiating a new tween:
为了解决这个问题,每个组件都可以创建自己的TWEEN.Group
(全局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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In this way, each component can handle creating, updating, and destroying its own set of tweens.
通过这种方式,每个组件都可以创建、更新和销毁自己的补间集合。
# Changing the easing function (AKA make it bouncy) 修改缓动函数(又名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. This is predictable but also quite uninteresting visually wise. Worry not--this behaviour can be easily changed using the easing method. For example:
js将以线性方式执行值之间的插值(即easing),所以变化会直接正比于经过的时间。这是可预测的,但在视觉上也相当无趣。不用担心——这种行为可以用easing方法轻易地改变。例如:
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 可用的缓动函数 :TWEEN.Easing
There are a few existing easing functions provided with 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.
tween.js
中提供了一些现有的缓动函数。它们是根据它们所代表的方程类型分组的:Linear
, Quadratic
, Cubic
, Quartic
, Quintic
, Sinusoidal
, Exponential
, Circular
, Elastic
, Back
和 Bounce
,然后通过缓动类型:In
, Out
和InOut
。
# 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:
您不仅可以使用任何现有的函数,而且还可以提供自己的函数,只要它遵循一些约定:
it must accept one parameter:
- k: the easing progress, or how far along the duration of the tween we are. Allowed values are in the range [0, 1].
it must return a value based on the input parameters.
它必须接受一个参数:
- k: easing的进度, 即动画运行到整个过程的哪个时刻。该值的范围是[0, 1].
它必须根据输入参数返回一个值。
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:
easing函数在每次update补间时只调用一次,不管要改变多少属性。然后将结果与初始值以及此值与最终值之间的差值(delta)一起使用,如此伪代码中所示:
easedElapsed = easing(k);
for each property:
newPropertyValue = initialPropertyValue + propertyDelta * easedElapsed;
2
3
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
}
2
3
And you could use it in a tween by simply calling its easing method, as we've seen before:
你可以在补间中使用它通过简单地调用它的easing方法,就像我们之前看到的那样:
tween.easing(tenStepEasing)
# Callbacks 回调
Another powerful feature is to be able to run your own functions at specific times in each tween's life cycle. This is usually required when changing properties is not enough.
另一个强大的特性是能够在每个tween生命周期的特定时间运行自己的函数。当更改属性还不够时,通常需要这样做。
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.
例如,假设您正在尝试使一些不能直接访问其属性但需要调用setter的对象具有动画效果。您可以使用更新回调来读取新的更新值,然后手动调用setter。所有回调都将补间对象作为唯一参数传递。
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)
})
2
3
4
5
6
7
8
9
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()
})
2
3
The scope for each callback is the tweened object--in this case, obj.
每个回调的scope是补间对象——在本例中是obj。
# onStart
Executed right before the tween starts animating, after any delay time specified by the delay method. This will be executed only once per tween, i.e. it will not be run when the tween is repeated via repeat().
在补间动画开始之前执行,在delay方法指定的延迟时间之后执行。这将在每个补间中只执行一次,也就是说,当通过repeat()重复补间时,它将不会运行。
It is great for synchronising to other events or triggering actions you want to happen when a tween starts.
当tween开始时,它非常适合与其他事件同步或触发您想要发生的动作。
The tweened object is passed in as the first parameter.
补间对象作为第一个参数传入。
# onStop
Executed when a tween is explicitly stopped via stop(), but not when it is completed normally, and before stopping any possible chained tween.
The tweened object is passed in as the first parameter.
当补间通过stop()显式停止时执行,但不是在补间正常完成时,以及在停止任何可能的链式补间之前执行。
补间对象作为第一个参数传入。
# onUpdate
Executed each time the tween is updated, after the values have been actually updated.
The tweened object is passed in as the first parameter.
在值实际更新之后,每次更新补间时执行。
补间对象作为第一个参数传入。
# onComplete
Executed when a tween is finished normally (i.e. not stopped).
The tweened object is passed in as the first parameter.
当补间正常完成时执行(即未停止)。
补间对象作为第一个参数传入。
# onRepeat
Executed whenever a tween has just finished one repetition and will begin another.
The tweened object is passed in as the first parameter.
当一个补间刚刚完成一次重复并将开始另一次重复时执行。
补间对象作为第一个参数传入。
# Advanced tweening 高级用法
# Relative values 相对值
You can also use relative values when using the to method. 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. But you need to use quotes or the values will be taken as absolute. Let's see this with an example:
在使用to
方法时,也可以使用相对值。当补间开始时,tween .js
将读取当前属性值并应用相对值来找到新的最终值。但是您需要使用引号,否则值将被视为绝对值。让我们看一个例子:
// 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Tweening nested objects 嵌套的补间对象
Tween.js can also change properties across nested objects. For example:
Tween.js还可以改变嵌套对象的属性。例如:
var nestedObject = {scale: {x: 0, y: 0}, alpha: 0}
var tween = new TWEEN.Tween(nestedObject).to({scale: {x: 100, y: 100}, alpha: 1})
2
# 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. To do this, you just need to specify an array of values instead of a single value for a property. For example:
除了渐变到绝对值或相对值之外,你还可以让Tween.js
改变一系列值的属性。为此,您只需要为属性指定一个值数组,而不是单个值。例如:
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:
这些值的计算方法如下:
first the tween progress is calculated as usual
the progress (from 0 to 1) is used as input for the interpolation function
based on the progress and the array of values, an interpolated value is generated
首先,像往常一样计算补间进度
进程(从0到1)用作插值函数的输入
根据进度和值的数组,生成一个插值值
For example, when the tween has just started (progress is 0), the interpolation function will return the first value in the array. 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. For example:
例如,当补间刚刚开始时(进度为0),插值函数将返回数组中的第一个值。当补间处于中间时,插值函数将返回一个近似于数组中间的值,当补间处于末尾时,插值函数将返回最后一个值。
你可以用interpolation
方法改变插值函数。例如:
tween.interpolation(TWEEN.Interpolation.Bezier)
The following values are available:
取值包括:
- TWEEN.Interpolation.Linear
- TWEEN.Interpolation.Bezier
- TWEEN.Interpolation.CatmullRom
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;你应该使用两个在同一个对象上运行的补间对象,但是修改不同的属性和使用不同的插值函数。
# 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. 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试图自己实现性能时,没有什么可以阻止你以一种反性能的方式使用它。这里有一些方法可以避免在使用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:
当你试图动画化页面中元素的位置时,最简单的解决方案是动画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'
})
2
3
4
5
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
,它不会使布局失效,也会在可能的情况下硬件加速,像这样:
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)'
})
2
3
4
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. 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, etc.
然而,如果您的动画需求是如此简单,那么在适用的情况下,最好使用CSS动画或过渡,这样浏览器就可以尽可能地进行优化。当你的动画需要涉及复杂的安排时,Tween.js是最有用的,例如,你需要同步几个tween在一起,在一个完成后有一些开始,循环他们多次,等等。
# Be good to the Garbage collector (alias the GC) 善待垃圾处理器
If you use an onUpdate callback, you need to be very careful with what you put on it. 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. 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回调,你需要非常小心你放进去的东西。这个函数每秒会被调用很多次,所以如果你在每次更新上执行代价高昂的操作,你可能会阻塞主线程并导致可怕的崩溃,或者——如果你的操作涉及内存分配,你最终会让垃圾收集器运行得太频繁,也会导致崩溃。所以这两件事都不要做。保持onUpdate回调非常轻量级,并确保在开发时也使用内存分析器。