Home > Web Front-end > JS Tutorial > body text

tween.js Chinese usage guide

小云云
Release: 2018-01-08 09:24:33
Original
5532 people have browsed it

This article mainly introduces the detailed Chinese usage guide of tween.js. The editor thinks it is quite good. Now I will share it with you and give it as a reference. Let’s follow the editor to take a look, I hope it can help everyone.

Tweening (animation) is a concept that allows you to change the properties of an object in a smooth way. You just tell it which properties you want to change, what final values ​​they should have when the tween finishes running, and how long this should take, and the tween engine will take care of calculating the values ​​from the start point to the end point.

For example, the position object has two coordinates, x and y:


var position = { x: 100, y: 0 }
Copy after login

If you want to change the value of the x coordinate from 100 to 200, you should Do this:


// 首先为位置创建一个补间(tween)
var tween = new TWEEN.Tween(position);

// 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置
tween.to({ x: 200 }, 1000);
Copy after login

Generally speaking, this is not enough. The tween has been created, but it has not been activated (used) yet. You need to start it like this:


// 启动
tween.start();
Copy after login

Finally, to successfully complete this effect, you need to call TWEEN.update in the main function, as follows:


animate();

function animate() {
 requestAnimationFrame(animate);
 // [...]
 TWEEN.update();
 // [...]
}
Copy after login
Copy after login

In this way, the tween animation will be run when updating each frame; after 1 second (1000 milliseconds) position.x will become 200.

Unless you print out the value of x in the console, you won't see its change. You may want to use the onUpdate callback:


tween.onUpdate(function(object) {
 console.log(object.x);
});
Copy after login

tips: You may not be able to get object.x here, see the issue I mentioned for details

This function will be called every time the animation updates; how often this happens depends on many factors - for example, how fast (and how busy) the computer or device is.

So far we have only used tweened animations to output values ​​to the console, but you can combine this with a three.js object:


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);
}
Copy after login

In this case, there is no need to use an explicit onUpdate callback because the three.js renderer will look at the object's position before rendering.

You may also notice some differences: tween.js can be called in a chain! Every tween function returns a tween instance, so you can rewrite the following code:


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

to this:


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

You'll see a lot of examples here, so it's good to get familiar with it! For example, 04-simplest is an example.

Animations for tween.js

Tween.js does not run on its own. You need to explicitly call the update method to tell it when to run. The recommended approach is to perform this operation within the main animation loop. Call this loop using requestAnimationFrame for optimal graphics performance.

For example, this example:


animate();

function animate() {
 requestAnimationFrame(animate);
 // [...]
 TWEEN.update();
 // [...]
}
Copy after login
Copy after login

If no parameters are passed in when calling, update will judge the current time point to determine the time since the last run. How long has it been.

Of course you can also pass an explicit time parameter to update


TWEEN.update(100);
Copy after login

It means "update time = 100 milliseconds". You can use this to ensure that all time-related functions in your code use the same time value. For example, let's say you have a player and want to run tweens synchronously. Your animate function might look like this:


var currentTime = player.currentTime;
TWEEN.update(currentTime);
Copy after login

We use explicit time values ​​for unit testing. You can take a look at the tests.js example to see how we call TWEEN.update() with different values ​​to simulate time transfer.

Controlling a tween

start and stop

So far, we have learned about the Tween.start method, But there are more ways to control individual tweens. Perhaps the most important one is star's counterpart: stop . If you want to cancel a tween, just call this method through a separate tween:


tween.stop();
Copy after login

Stopping a tween that has never started or has been stopped has no effect. No errors are thrown.

The start method accepts a parameter time. If you use this, then tweening will not start immediately until a specific moment, otherwise it will start as soon as possible (i.e. the next time TWEEN.update is called).

update

Tweens also have an update method --- this is actually called by TWEEN.update. You usually don't need to call it directly unless you are a crazy hacker.

chain

Things get interesting when you sequence different tweens, such as starting another tween as soon as the previous one ends . We call this chained tweening, and we do it using the chain method. So, to make tweenB start on tewwnA:


tweenA.chain(tweenB);
Copy after login

Or, for an infinite chain, set tweenA to start as soon as tweenB completes:


tweenA.chain(tweenB);
tweenB.chain(tweenA);
Copy after login

About infinite chain viewing Hello world.

In other cases, you may need to link multiple tweens to another tweener so that they (the linked tweens) start animation at the same time:


tweenA.chain(tweenB,tweenC);
Copy after login

Warning: Calling tweenA.chain(tweenB) actually modifies tweenA, so tweenA is always started when tweenA completes. The return value of chain is only tweenA, not a new tween.

repeat

如果你想让一个补间永远重复,你可以链接到自己,但更好的方法是使用 repeat 方法。 它接受一个参数,描述第一个补间完成后需要多少次重复


tween.repeat(10); // 循环10次
tween.repeat(Infinity); // 无限循环
Copy after login

补间的总次数将是重复参数加上一个初始补间。查看 Repeat。

yoyo

这个功能只有在独自使用 repeat 时才有效果。 活跃时,补间的行为将像 yoyo 一样,i.e 它会从起始值和结束值之间跳出,而不是从头开始重复相同的顺序。

delay

更复杂的安排可能需要在实际开始运行之前延迟补间。 你可以使用 delay 方法来做到这一点


tween.delay(1000);
tween.start();
Copy after login

将在调用启动方法后的1秒钟后开始执行。

控制所有补间

在 TWEEN 全局对象中可以找到以下方法,除了 update 之外,通常不需要使用其中的大部分对象。

TWEEN.update(time)

我们已经讨论过这种方法。 它用于更新所有活动的补间。

如果 time 不指定,它将使用当前时间。

TWEEN.getAll and TWEEN.removeAll

用于获取对活动 tweens 数组的引用,并分别仅从一个调用中将它们全部从数组中删除

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

用于将补间添加到活动补间的列表,或者分别从列表中删除特定的补间。

这些方法通常只在内部使用,但是如果您想要做一些有趣的事情,则会被暴露。

控制补间组

使用 TWEEN 单例来管理补间可能会导致包含许多组件的大型应用程序出现问题。 在这些情况下,您可能希望创建自己的更小的补间组。

示例:交叉组件冲突

如果使用 TWEEN 有多个组件,并且每个组件都想管理自己的一组补间,则可能发生冲突。 如果一个组件调用 TWEEN.update() 或 TWEEN.removeAll(),则其他组件的补间也将被更新或删除。

创建你自己的补间组

为了解决这个问题,每个组件都可以创建自己的 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(); // 只更新tweenA
groupB.update(); // 只更新tweenB
TWEEN.update(); // 只更新tweenC

groupA.removeAll(); // 只移除tweenA
groupB.removeAll(); // 只移除tweenB
TWEEN.removeAll(); // 只移除tweenC
Copy after login

通过这种方式,每个组件都可以处理创建,更新和销毁自己的一组补间。

改变缓动功能

Tween.js 将以线性方式执行值之间的插值(即缓动),所以变化将与流逝的时间成正比。 这是可以预见的,但在视觉上也是相当无趣的。 不要担心 - 使用缓动方法可以轻松更改此行为。 例如:


tween.easing(TWEEN.Easing.Quadratic.In);
Copy after login

这将导致缓慢地开始向最终值变化,向中间加速,然后迅速达到其最终值,相反,TWEEN.Easing.Quadratic.Out 一开始会加速,但随着值的接近最终放缓。

可用的缓动函数:TWEEN.Easing

tween.js提供了一些现有的缓动功能。它们按照它们表示的方程式进行分组:线性,二次,三次,四次,五次,正弦,指数,圆形,弹性,背部和弹跳,然后是缓动型:In,Out和InOut。

除非您已经熟悉这些概念,否则这些名称可能不会对您说什么,所以您可能需要查看 Graphs 示例,该示例将一个页面中的所有曲线进行图形化,以便比较它们如何看待一瞥。

这些功能是从 Robert Penner 慷慨地提供几年前作为自由软件提供的原始方程派生而来的,但是已经被优化以便与JavaScript很好地发挥作用。

使用自定义缓动功能

您不仅可以使用任何现有的功能,还可以提供您自己的功能,只要遵循一些约定即可:

它必须接受一个参数:

k: 缓动过程,或我们的补间所处的时间有多长。允许的值在[0,1]的范围内。

它必须根据输入参数返回一个值。

不管要修改多少个属性,easing函数在每次更新时只调用一次。 然后将结果与初始值以及这个值和最终值之间的差值(delta)一起使用,就像这个伪代码一样:


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

对于更注重性能表现的人来说:只有在补间上调用 start() 时才会计算增量值。

因此,让我们假设您想使用一个缓解值的自定义缓动函数,但是将 Math.floor 应用于输出,所以只返回整数部分,从而产生一种梯级输出:


function tenStepEasing(k) {
 return Math.floor(k * 10) / 10;
}
Copy after login

你可以通过简单地调用它的缓动方法来使用它,就像我们之前看到的那样:


tween.easing(tenStepEasing);
Copy after login

查看 graphs for custom easing functions 示例,以查看这个动作(还有一些用于生成步进函数的元编程)。

回调函数

另一个强大的特性是能够在每个补间的生命周期的特定时间运行自己的功能。 当更改属性不够时,通常需要这样做。

例如,假设你正在试图给一些不能直接访问属性的对象设置动画,但是需要你调用setter。 您可以使用 update 回调来读取新的更新值,然后手动调用setters。 所有的回调函数都将补间对象作为唯一的参数。


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 );
 });
Copy after login

或者想象一下,当一个补间开始时,你想播放声音。你可以使用 start 回调:


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

每个回调的范围是补间对象--在这种情况下,是 obj。

onStart

在补间开始之前执行--i.e. 在计算之前。每个补间只能执行一次,i.e. 当通过 repeat() 重复补间时,它将不会运行。

同步到其他事件或触发您要在补间启动时发生的操作是非常好的。

补间对象作为第一个参数传入。

onStop

当通过 stop() 显式停止补间时执行,但在正常完成时并且在停止任何可能的链补间之前执行补间。

补间对象作为第一个参数传入。

onUpdate

每次补间更新时执行,实际更新后的值。

补间对象作为第一个参数传入。

onComplete

当补间正常完成(即不停止)时执行。

补间对象作为第一个参数传入。

高级补间

相对值

使用 to 方法时,也可以使用相对值。 当tween启动时,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
Copy after login

查看09_relative_values 示例。

补间值的数组

除了补间为绝对值或相对值之外,还可以让Tween.js跨一系列值更改属性。 要做到这一点,你只需要指定一个数组的值,而不是一个属性的单个值。 例如:


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

将使 x 从初始值变为0,-100和100。

这些值的计算方法如下:

  1. 首先,补间进度如常计算

  2. 进度(从0到1)用作插值函数的输入

  3. 基于进度和值的数组,生成内插值

例如,当补间刚刚启动(进度为0)时,插值函数将返回数组中的第一个值。 当补间到一半时,插值函数将返回一个大约在数组中间的值,当补间结束时,插值函数将返回最后一个值。

您可以使用插值方法更改插值函数。 例如:


tween.interpolation( TWEEN.Interpolation.Bezier );
Copy after login

以下值可用:

  1. TWEEN.Interpolation.Linear

  2. TWEEN.Interpolation.Bezier

  3. TWEEN.Interpolation.CatmullRom

默认是 Linear。

请注意,插值函数对于与同一补间中的数组进行补间的所有属性是全局的。
您不能使用数组和线性函数进行属性A的更改,也不能使用相同的补间进行数组B的属性B和Bezier函数的更改; 您应该使用运行在同一对象上的两个补间对象,但修改不同的属性并使用不同的插值函数。

查看 06_array_interpolation 示例。

获得最佳性能

虽然Tween.js试图自己执行,但是没有什么能够阻止你以一种反作用的方式使用它。 这里有一些方法可以避免在使用Tween.js时(或者在网页中进行动画制作时)减慢项目速度。

使用高性能的CSS

当您尝试在页面中设置元素的位置时,最简单的解决方案是为 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';
 });
Copy after login

但这实际上是效率低下的,因为改变这些属性会迫使浏览器在每次更新时重新计算布局,这是非常昂贵的操作。 相反的,您应该使用 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);';
 });
Copy after login

但是,如果您的动画需求非常简单,那么在适用的情况下使用CSS动画或转换可能会更好,以便浏览器尽可能优化。
当您的动画需要涉及复杂的布局时,Tween.js是非常有用的,也就是说,您需要将多个补间同步到一起,在完成一些动作之后,循环多次等等。

对垃圾收集器(别名GC)

If you use the onUpdate callback function, you need to use it very carefully. Because this function will be called many times per second, if each update costs a lot, you may block the main thread and cause terrible results, or if your operation involves memory allocation, garbage collection Running the server too frequently can also cause problems. So just don't do one of those things. Keep your onUpdate callbacks very lightweight and make sure to use a memory profiler while developing as well.

Crazy Tweens

This is something you may not use often, but you can use the tweening formula outside of Tween.js. After all, they are just functions. So you can use them to calculate smooth curves as input data.

For example, they were used to generate audio data in this experiment.

Related recommendations:

Detailed explanation of usage examples of tween.js

Simple animation library encapsulation tween.js example tutorial

Tween.js animation detailed introduction

The above is the detailed content of tween.js Chinese usage guide. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!