Cet article présente principalement le guide détaillé d'utilisation du chinois de tween.js. L'éditeur pense qu'il est plutôt bon. Maintenant, je vais le partager avec vous et le donner comme référence. Suivons l'éditeur pour y jeter un œil, j'espère que cela pourra aider tout le monde.
L'interpolation (animation) est un concept qui permet de modifier les propriétés d'un objet de manière fluide. Vous lui dites simplement quelles propriétés vous souhaitez modifier, quelles valeurs finales elles devraient avoir lorsque l'interpolation aura fini de fonctionner et combien de temps cela devrait prendre, et le moteur d'interpolation se chargera de calculer les valeurs depuis le point de départ jusqu'à le point final.
Par exemple, l'objet position a deux coordonnées : Vous devriez faire ceci :
var position = { x: 100, y: 0 }
D'une manière générale, cela n'est pas suffisant. a été créé, mais il n'a pas encore été activé (utilisé) Vous devez le démarrer comme ceci :
// 首先为位置创建一个补间(tween) var tween = new TWEEN.Tween(position); // 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置 tween.to({ x: 200 }, 1000);
Enfin, pour réussir cet effet, vous devez pour appeler TWEEN.update dans la fonction principale, comme suit :
// 启动 tween.start();
De cette façon, l'animation interpolée sera exécutée lors de la mise à jour de chaque image après 1 seconde ( 1000 millisecondes) position.x deviendra 200.
Vous ne verrez pas le changement de x à moins que vous imprimiez la valeur de x sur la console. Vous souhaiterez peut-être utiliser le rappel onUpdate :
animate(); function animate() { requestAnimationFrame(animate); // [...] TWEEN.update(); // [...] }
conseils : vous ne pourrez peut-être pas obtenir object.x ici, voir le problème que j'ai mentionné pour plus de détails
Cette fonction sera appelée à chaque fois que l'animation est mise à jour ; la fréquence à laquelle cela se produit dépend de nombreux facteurs - par exemple, la vitesse (et l'occupation) de l'ordinateur ou de l'appareil.
tween.onUpdate(function(object) { console.log(object.x); });
Dans ce cas, il n'est pas nécessaire d'utiliser un rappel onUpdate explicite car le moteur de rendu three.js examinera la position de l'objet avant le rendu.
Vous remarquerez peut-être aussi quelque chose de différent : tween.js peut être appelé en chaîne ! Chaque fonction tween renvoie une instance tween, vous pouvez donc réécrire le code suivant :
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); }
en ceci :
var tween = new TWEEN.Tween(position); tween.to({ x: 200 }, 1000); tween.start();
Vous verrez beaucoup d'exemples ici, donc c'est bien de se familiariser avec ! Par exemple, 04-simplest est un exemple.
Les animations de tween.js
var tween = new TWEEN.Tween(position) .to({ x: 200 }, 1000) .start();
Tween.js ne fonctionnera pas tout seul. Vous devez appeler explicitement la méthode update pour lui indiquer quand l'exécuter. L'approche recommandée consiste à effectuer cette opération dans la boucle d'animation principale. Appelez cette boucle en utilisant requestAnimationFrame pour des performances graphiques optimales.
Par exemple, dans l'exemple précédent :
Si aucun paramètre n'est transmis lors de l'appel, update jugera le moment actuel pour déterminer le temps écoulé depuis la dernière Combien de temps a-t-il fonctionné depuis.
Bien sûr, vous pouvez également passer un paramètre de temps explicite pour mettre à jour
animate(); function animate() { requestAnimationFrame(animate); // [...] TWEEN.update(); // [...] }
signifiant "temps de mise à jour = 100 millisecondes". Vous pouvez l'utiliser pour garantir que toutes les fonctions liées au temps dans votre code utilisent la même valeur temporelle. Par exemple, disons que vous avez un joueur et que vous souhaitez exécuter des préadolescents de manière synchrone. Votre fonction d'animation pourrait ressembler à ceci :
TWEEN.update(100);
Nous utilisons des valeurs de temps explicites pour les tests unitaires. Vous pouvez jeter un œil à l'exemple tests.js pour voir comment nous appelons TWEEN.update() avec différentes valeurs pour simuler le transfert de temps.
Contrôler un interpolation
var currentTime = player.currentTime; TWEEN.update(currentTime);
Jusqu'à présent, nous avons découvert la méthode Tween.start, mais il existe d'autres moyens de contrôler les préadolescents individuels. Le plus important est peut-être la contrepartie de l’étoile : stop . Si vous souhaitez annuler une interpolation, appelez simplement cette méthode sur une interpolation distincte : Effect. Aucune erreur n'est générée.
La méthode start accepte un paramètre time. Si vous l'utilisez, l'interpolation ne démarrera pas immédiatement avant un moment précis, sinon elle démarrera dès que possible (c'est-à-dire la prochaine fois que TWEEN.update sera appelé).
updateLes préadolescents ont également une méthode de mise à jour --- celle-ci est en fait appelée par TWEEN.update. Vous n'avez généralement pas besoin de l'appeler directement, sauf si vous êtes un hacker fou.
tween.stop();
Les choses deviennent intéressantes lorsque vous séquencez différentes interpolations, comme par exemple démarrer une autre interpolation dès que la précédente se termine. Nous appelons cela l’interpolation en chaîne, et nous le faisons en utilisant la méthode de la chaîne. Donc, pour que tweenB démarre sur tewwnA :
Ou, pour une chaîne infinie, définissez tweenA pour qu'il démarre dès que tweenB est terminé :
À propos de la visualisation en chaîne infinie Bonjour tout le monde.
Dans d'autres cas, vous devrez peut-être lier plusieurs tweens à un autre tween pour qu'ils (les tweens liés) démarrent l'animation en même temps :
tweenA.chain(tweenB);
Attention : l'appel de tweenA.chain(tweenB) modifie en fait tweenA, donc tweenA est toujours démarré lorsque tweenA se termine. La valeur de retour de la chaîne est uniquement tweenA, pas une nouvelle interpolation.
tweenA.chain(tweenB); tweenB.chain(tweenA);
如果你想让一个补间永远重复,你可以链接到自己,但更好的方法是使用 repeat 方法。 它接受一个参数,描述第一个补间完成后需要多少次重复
tween.repeat(10); // 循环10次 tween.repeat(Infinity); // 无限循环
补间的总次数将是重复参数加上一个初始补间。查看 Repeat。
yoyo
这个功能只有在独自使用 repeat 时才有效果。 活跃时,补间的行为将像 yoyo 一样,i.e 它会从起始值和结束值之间跳出,而不是从头开始重复相同的顺序。
delay
更复杂的安排可能需要在实际开始运行之前延迟补间。 你可以使用 delay 方法来做到这一点
tween.delay(1000); tween.start();
将在调用启动方法后的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
通过这种方式,每个组件都可以处理创建,更新和销毁自己的一组补间。
改变缓动功能
Tween.js 将以线性方式执行值之间的插值(即缓动),所以变化将与流逝的时间成正比。 这是可以预见的,但在视觉上也是相当无趣的。 不要担心 - 使用缓动方法可以轻松更改此行为。 例如:
tween.easing(TWEEN.Easing.Quadratic.In);
这将导致缓慢地开始向最终值变化,向中间加速,然后迅速达到其最终值,相反,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;
对于更注重性能表现的人来说:只有在补间上调用 start() 时才会计算增量值。
因此,让我们假设您想使用一个缓解值的自定义缓动函数,但是将 Math.floor 应用于输出,所以只返回整数部分,从而产生一种梯级输出:
function tenStepEasing(k) { return Math.floor(k * 10) / 10; }
你可以通过简单地调用它的缓动方法来使用它,就像我们之前看到的那样:
tween.easing(tenStepEasing);
查看 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 ); });
或者想象一下,当一个补间开始时,你想播放声音。你可以使用 start 回调:
var tween = new TWEEN.Tween(obj) .to({ x: 100 }) .onStart(function() { sound.play(); });
每个回调的范围是补间对象--在这种情况下,是 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
查看09_relative_values 示例。
补间值的数组
除了补间为绝对值或相对值之外,还可以让Tween.js跨一系列值更改属性。 要做到这一点,你只需要指定一个数组的值,而不是一个属性的单个值。 例如:
var tween = new TWEEN.Tween(relativeObj).to({ x: [0, -100, 100] });
将使 x 从初始值变为0,-100和100。
这些值的计算方法如下:
首先,补间进度如常计算
进度(从0到1)用作插值函数的输入
基于进度和值的数组,生成内插值
例如,当补间刚刚启动(进度为0)时,插值函数将返回数组中的第一个值。 当补间到一半时,插值函数将返回一个大约在数组中间的值,当补间结束时,插值函数将返回最后一个值。
您可以使用插值方法更改插值函数。 例如:
tween.interpolation( TWEEN.Interpolation.Bezier );
以下值可用:
TWEEN.Interpolation.Linear
TWEEN.Interpolation.Bezier
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'; });
但这实际上是效率低下的,因为改变这些属性会迫使浏览器在每次更新时重新计算布局,这是非常昂贵的操作。 相反的,您应该使用 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);'; });
但是,如果您的动画需求非常简单,那么在适用的情况下使用CSS动画或转换可能会更好,以便浏览器尽可能优化。
当您的动画需要涉及复杂的布局时,Tween.js是非常有用的,也就是说,您需要将多个补间同步到一起,在完成一些动作之后,循环多次等等。
对垃圾收集器(别名GC)
Si vous utilisez la fonction de rappel onUpdate, vous devez l'utiliser avec beaucoup de prudence. Étant donné que cette fonction sera appelée plusieurs fois par seconde, si chaque mise à jour coûte cher, vous risquez de bloquer le thread principal et de provoquer des résultats terribles, ou si votre opération implique une allocation de mémoire, un garbage collection L'exécution trop fréquente du serveur peut également causer des problèmes. Alors ne faites pas une de ces choses. Gardez vos rappels onUpdate très légers et assurez-vous d'utiliser également un profileur de mémoire lors du développement.
Crazy Tweens
C'est quelque chose que vous n'utiliserez peut-être pas très souvent, mais vous pouvez utiliser la formule d'interpolation en dehors de Tween.js. Après tout, ce ne sont que des fonctions. Vous pouvez donc les utiliser pour calculer des courbes lisses comme données d'entrée.
Par exemple, ils ont été utilisés pour générer des données audio dans cette expérience.
Recommandations associées :
Explication détaillée des exemples d'utilisation de tween.js
Une simple encapsulation de bibliothèque d'animation tween.js exemple de tutoriel
Introduction détaillée à l'animation Tween.js
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!