走向 “Meta GSAP”。对 "完美 "无限滚动的追求
有一件事常常被GSAP所忽视,那就是你几乎可以用它来制作任何东西的动画。这通常是因为当想到动画时,视觉上的东西会浮现在脑海中。我们的第一个想法并不是把这个过程带到一个Meta的层面,从后退一步开始做动画。
但是,在更大的范围内思考动画工作,然后把它分解成若干层。例如,你播放一部动画片。这部动画片是一个构图的集合。每个构图都是一个场景。然后你有能力用遥控器擦过这些构图的集合,无论是在电脑上,还是用你的电视遥控器,或其他什么。正在发生的事情几乎有三个层次。
这就是我们需要的创造不同类型的无限循环的技巧。这就是这里的主要概念。我们用一条时间线将一个时间线的播放头的位置做成动画。然后我们可以用我们的滚动位置来刷新这个时间线。
如果这听起来很混乱,请不要担心。我们将把它分解开来。
走向 “Meta” 时代
让我们从一个例子开始。我们将创建一个Tween,从左到右移动一些盒子。这就是它。
十个盒子,一直从左到右。这在Greensock中是很直接的。在这里,我们使用fromTo和repeat来保持动画的进行。但是,我们在每个迭代的开始有一个间隙。我们还使用了交错的方式来拉开运动的空间,这一点将在我们继续的过程中发挥重要作用。
gsap.fromTo('.box', {
xPercent: 100
}, {
xPercent: -200,
stagger: 0.5,
duration: 1,
repeat: -1,
ease: 'none',
})
现在,有趣的部分来了。让我们暂停这个Tween,并将其分配给一个变量。然后让我们创建一个播放它的Tween。我们可以通过调整tween的totalTime来做到这一点,这使我们能够获得或设置tween的播放头的tween,同时考虑重复和重复延迟。
const SHIFT = gsap.fromTo('.box', {
xPercent: 100
}, {
paused: true,
xPercent: -200,
stagger: 0.5,
duration: 1,
repeat: -1,
ease: 'none',
})
const DURATION = SHIFT.duration()
gsap.to(SHIFT, {
totalTime: DURATION,
repeat: -1,
duration: DURATION,
ease: 'none',
})
这是我们的第一个 “Meta” Tween。它看起来完全一样,但我们增加了另一个控制层次。我们可以在不影响原层的情况下改变这一层的东西。例如,我们可以把tween的难易度改为power4.in。这完全改变了动画,但不影响底层动画。我们有点像用后退来保护自己。
不仅如此,我们可能选择只重复时间线的某一部分。我们可以用另一个fromTo做到这一点,就像这样。
这方面的代码将是这样的:
gsap.fromTo(SHIFT, {
totalTime: 2,
}, {
totalTime: DURATION - 1,
repeat: -1,
duration: DURATION,
ease: 'none'
})
你知道这是要去哪里吗?请注意这个间隔。虽然它一直在循环,但每次重复时数字都会翻转。但是,这些方框都在正确的位置。
实现 "完美 "循环
如果我们回到原来的例子,每次重复之间有一个明显的间隙。
诀窍来了。解锁一切的部分。我们需要建立一个完美的循环。
让我们从重复移位三次开始。注意我们是如何从Tween中移除 repeat: -1 的。
const getShift = () => gsap.fromTo('.box', {
xPercent: 100
}, {
xPercent: -200,
stagger: 0.5,
duration: 1,
ease: 'none',
})
const LOOP = gsap.timeline()
.add(getShift())
.add(getShift())
.add(getShift())
我们把最初的Tween变成一个函数,返回Tween,并把它添加到一个新的时间轴上,一共三次。这样我们就得到了以下结果。
但是,仍然有一个缺口。现在我们可以引入位置参数,用于添加和定位这些微调。我们希望它是无缝的。这意味着在前一组结束之前插入每一组推子。这是一个基于错开和元素数量的值。
const stagger = 0.5
const BOXES = gsap.utils.toArray('.box')
const LOOP = gsap.timeline({
repeat: -1
})
.add(getShift(), 0)
.add(getShift(), BOXES.length * stagger)
.add(getShift(), BOXES.length * stagger * 2)
如果我们更新我们的时间线,重复观看(同时调整错开的时间,看它如何影响事情)…
你会注意到,中间有一个窗口,创造了一个 "无缝 "循环。还记得之前