이 글은 주로 tween.js의 자세한 중국어 사용 가이드를 소개하고 있어서 편집자가 꽤 좋다고 생각해서 지금 공유하고 참고용으로 올려보겠습니다. 편집자를 따라 살펴보겠습니다. 모두에게 도움이 되기를 바랍니다.
트위닝(애니메이션)은 개체의 속성을 원활하게 변경할 수 있는 개념입니다. 변경하려는 속성, 트윈 실행이 완료될 때 가져야 하는 최종 값, 이 작업에 걸리는 시간을 알려주면 트윈 엔진이 시작 지점부터 다음 지점까지의 값을 계산합니다. 끝점.
예를 들어 위치 개체에는 x와 y라는 두 개의 좌표가 있습니다.
var position = { x: 100, y: 0 }
x 좌표 값을 100에서 200으로 변경하려면 다음을 수행해야 합니다.
// 首先为位置创建一个补间(tween) var tween = new TWEEN.Tween(position); // 然后告诉 tween 我们想要在1000毫秒内以动画的形式移动 x 的位置 tween.to({ x: 200 }, 1000);
일반적으로 충분하지 않습니다. 트윈이 생성되었지만 아직 활성화(사용)되지 않았습니다. 다음과 같이 시작해야 합니다.
// 启动 tween.start();
마지막으로 이 효과를 성공적으로 완료하려면 다음이 필요합니다. 기본 함수에서 TWEEN.update를 호출하려면 다음과 같이 사용하세요.
animate(); function animate() { requestAnimationFrame(animate); // [...] TWEEN.update(); // [...] }
이런 식으로 각 프레임을 업데이트할 때 트윈 애니메이션이 실행되며 1초(1000밀리초) 후에 position.x가 200이 됩니다.
콘솔에서 x 값을 인쇄하지 않으면 x의 변경 사항을 볼 수 없습니다. onUpdate 콜백을 사용할 수 있습니다.
tween.onUpdate(function(object) { console.log(object.x); });
팁: 여기에서 object.x를 가져오지 못할 수도 있습니다. 자세한 내용은 제가 언급한 이 문제를 참조하세요. 애니메이션이 업데이트될 때마다 호출됩니다. 호출되는 빈도는 여러 가지 요인(예: 컴퓨터나 장치의 속도(및 사용량))에 따라 달라집니다.
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); }
이 경우 three.js 렌더러는 렌더링하기 전에 객체의 위치를 지정하므로 명시적인 onUpdate 콜백을 사용할 필요가 없습니다.
var tween = new TWEEN.Tween(position); tween.to({ x: 200 }, 1000); tween.start();
에서
var tween = new TWEEN.Tween(position) .to({ x: 200 }, 1000) .start();
로 다시 작성할 수 있습니다. 여기서는 많은 예제를 볼 수 있으므로 익숙해지는 것이 좋습니다! 예를 들어 04-simplest가 그 예입니다.
tween.js animations
Tween.js는 자체적으로 실행되지 않습니다. 실행할 시기를 알려주려면 업데이트 메서드를 명시적으로 호출해야 합니다. 권장되는 접근 방식은 기본 애니메이션 루프 내에서 이 작업을 수행하는 것입니다. 최적의 그래픽 성능을 위해 requestAnimationFrame을 사용하여 이 루프를 호출하세요.
예를 들어 다음 예는 다음과 같습니다.animate(); function animate() { requestAnimationFrame(animate); // [...] TWEEN.update(); // [...] }
호출 시 매개변수가 전달되지 않으면 업데이트는 현재 시점을 판단하여 마지막 실행 이후 얼마나 오랜 시간이 지났는지 확인합니다.
TWEEN.update(100);
에 전달할 수도 있습니다. 이를 사용하여 코드의 모든 시간 관련 함수가 동일한 시간 값을 사용하도록 할 수 있습니다. 예를 들어 플레이어가 있고 트윈을 동기식으로 실행하려고 한다고 가정해 보겠습니다. 애니메이션 기능은 다음과 같습니다.
var currentTime = player.currentTime; TWEEN.update(currentTime);
단위 테스트에는 명시적인 시간 값을 사용합니다. 시간 전송을 시뮬레이션하기 위해 다양한 값으로 TWEEN.update()를 호출하는 방법을 보려면 test.js 예제를 살펴보세요.
트윈 제어
시작 및 중지
지금까지 Tween.start 메서드를 살펴보았지만 단일 트윈을 제어하는 방법은 더 많습니다. 아마도 가장 중요한 것은 star의 대응 부분인 stop 입니다. 트윈을 취소하려면 별도의 트윈을 통해 다음 메서드를 호출하면 됩니다.
tween.stop();
시작되지 않았거나 중지된 트윈을 중지해도 아무런 효과가 없습니다. 오류가 발생하지 않습니다.
update
Tweens에도 업데이트 방법이 있습니다. 이는 실제로 TWEEN.update에 의해 호출됩니다. 당신이 미친 해커가 아니라면 일반적으로 직접 호출할 필요는 없습니다.
chain
이전 트윈이 끝나자마자 다른 트윈을 시작하는 등 다양한 트윈을 시퀀스하면 상황이 흥미로워집니다. 우리는 이것을 체인 트위닝이라고 부르며, 체인 메소드를 사용하여 이 작업을 수행합니다. 따라서 tweenB가 tewwnA에서 시작되도록 하려면:
tweenA.chain(tweenB);
또는 무한 체인의 경우 tweenB가 완료되자마자 tweenA가 시작되도록 설정합니다.
tweenA.chain(tweenB); tweenB.chain(tweenA);
무한 체인의 경우 Hello world를 참조하세요.
tweenA.chain(tweenB,tweenC);
경고: tweenA.chain(tweenB) 호출 실제로 tweenA를 tweenA로 수정함 tweenA가 완료되면 항상 시작됩니다. 체인의 반환 값은 새 트윈이 아닌 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)
onUpdate 콜백 함수를 사용하는 경우 매우 신중하게 사용해야 합니다. 이 함수는 초당 여러 번 호출되기 때문에 각 업데이트 비용이 많이 들 경우 메인 스레드를 차단하여 끔찍한 결과를 초래할 수 있으며, 작업에 메모리 할당, 가비지 수집이 포함되는 경우 서버를 너무 자주 실행하는 경우에도 문제가 발생할 수 있습니다. 그러니 그런 일 중 하나를 수행하지 마십시오. onUpdate 콜백을 매우 가볍게 유지하고 개발하는 동안에도 메모리 프로파일러를 사용해야 합니다.
Crazy Tweens
이것은 자주 사용하지 않을 수도 있지만 Tween.js 외부에서 트위닝 공식을 사용할 수 있습니다. 결국, 그것들은 단지 기능일 뿐입니다. 따라서 이를 사용하여 부드러운 곡선을 입력 데이터로 계산할 수 있습니다.
예를 들어 이 실험에서는 오디오 데이터를 생성하는 데 사용되었습니다.
관련 권장사항:
간단한 애니메이션 라이브러리 캡슐화 tween.js 예제 튜토리얼
위 내용은 tween.js 중국어 사용 가이드의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!