欢迎回到 Popmotion 简介系列教程。在第 1 部分中,我们发现了如何使用补间和关键帧来制作精确的、按时间安排的动画。
在第 2 部分中,我们将研究指针跟踪和基于速度的动画。
指针跟踪允许我们创建可滚动的产品货架、自定义值滑块或拖放界面。
基于速度的动画与基于时间的动画(如补间)不同,影响动画行为方式的主要属性是 velocity
. 动画本身可能需要任何时间。
我们将看看 Popmotion 中的三个基于速度的动画 spring
, decay
、 和 physics
。我们将使用 velocity
指针跟踪动画来启动这些动画,这将演示基于速度的动画如何以基于时间的动画无法创建的方式创建引人入胜且有趣的 UI。
首先,打开这个 CodePen一起玩。
指针跟踪
Popmotion 提供了 跟踪和输出鼠标或单点触摸指针坐标的pointer
功能。
让我们将它与 一起导入 styler
,这将允许我们设置球的位置。
const { pointer, styler } = popmotion; const ball = document.queryselector('.ball'); const ballStyler = styler(ball);
对于此示例,我们要拖动球。让我们添加一个事件,将指针的位置输出到球:
let pointerTracker; const startTracking = () => { pointerTracker = pointer().start(ballStyler.set); }; ball.addeventListener('mousedown', startTracking); ball.addEventListener('touchstart', startTracking);
我们还需要一些代码在我们释放球时停止跟踪:
const stopTracking = () => pointerTracker && pointerTracker.stop(); document.addEventListener('mouseup', stopTracking); document.addEventListener('touchend', stopTracking);
如果您现在尝试拖动球,就会出现明显的问题。当我们触摸它时,球会跳开!不是很好的用户体验。
这是因为,默认情况下, pointer
输出指针 相对于页面的位置。
要输出指针 相对于另一个点的位置,在这种情况下是球的 x/y 变换,我们可以简单地将该位置传递给 pointer
这样的:
const startTracking = () => { pointerTracker = pointer({ x: ballStyler.get('x'), y: ballStyler.get('y') }).start(ballStyler.set); };
现在你已经用很少的几行代码让球可以拖动了!然而,当用户释放球时,它就停止了。
这并不令人满意:想象一个可滚动的产品轮播,用户可以拖动它来滚动。如果它只是停止而不是动量滚动,那么使用起来会不太愉快。
这也会更难,因为滚动轮播所需的整体体力会更高。
要启用这样的动画,我们首先需要知道 velocity
被抛出的对象的类型。
跟踪速度
Popmotion 提供了一个可以帮助我们跟踪速度的功能。它被称为 value
。让我们导入:
const { pointer, styler, value } = popmotion;
暂时从技术上讲,Popmotion 的所有动画都称为 动作。动作是可以启动和停止的反应性值流。
value
相反, A是一个反应。它无法停止或启动。它只是在 update
调用其方法时被动响应。它可以跟踪值并可以用来查询它们的速度。
所以,在我们定义之后 ballStyler
,让我们定义一个新 value
的 for ballXY
:
const ballXY = value({ x: 0, y: 0 });
每当 ballXY
更新时,我们都想更新 ballStyler
. 我们可以将第二个参数传递给 value
,该函数将在 ballXY
更新时运行:
const ballXY = value({ x: 0, y: 0 }, ballStyler.set);
现在我们可以重写我们 pointer
的更新 ballXY
而不是ballStyler.set
:
const startTracking = () => { pointer(ballXY.get()) .start(ballXY); };
现在,在任何指针处,我们都可以调用 ballXY.getVelocity()
并且我们将接收到 和 的速度 x
, y
准备好插入我们基于速度的动画。
基于速度的动画
spring
要介绍的第一个基于速度的动画是 spring
. 它基于管理 Apple 的 CASpringAnimation 的相同方程式,即所有ios弹性俏皮背后的弹簧动画。
进口:
const { pointer, spring, styler, value } = popmotion;
现在,修改 stopTracking
它不是停止pointerTracker
动画,而是像这样开始一个 spring
动画:
const stopTracking = () => spring({ from: ballXY.get(), velocity: ballXY.getVelocity(), to: 0, stiffness: 100, damping: 20 }).start(ballXY);
我们向它提供球的当前位置、速度和目标,然后运行模拟。它会根据用户投球的方式而变化。
弹簧最酷的地方在于它们富有表现力。通过调整 mass
、 stiffness
和 damping
属性,您可以得到完全不同的弹簧感觉。
例如,如果您仅将 stiffness
上述更改为 1000
,则可以创建一个感觉就像高能捕捉的动作。然后,通过更改 mass
为 20
,您可以创建看起来几乎像重力的运动。
几乎在任何情况下,总有一种组合会让您的用户感到正确和满意,并且适合您的品牌。通过玩不同的弹簧感觉,您可以传达不同的感觉,例如严格的出界快照或更柔和的肯定弹跳。
decay
decay
动画,顾名思义, 衰减提供的 速度,使动画逐渐减慢到完全停止。
这可用于创建智能手机上的动量滚动效果,如下所示:
导入 decay
函数:
const { decay, pointer, spring, styler, value } = popmotion;
并将 函数替换为 以下内容:stopTracking
const stopTracking = () => decay({ from: ballXY.get(), velocity: ballXY.getVelocity() }).start(ballXY);
decay
根据提供的 from
和 velocity
道具自动计算一个新的目标。
可以通过弄乱上面链接的文档中概述的道具来调整减速的感觉,但与 spring
and 不同的是physics
, decay
它被设计为开箱即用。
physics
最后,我们有了 physics
动画。这是 Popmotion 的基于速度的动画的瑞士军刀。有了它,你可以模拟:
等速
加速度
弹簧
摩擦
spring
并 decay
提供超精确的运动和更广泛的“感觉”。很快,它们都将是可擦洗的。
但两者都是 不可变的。一旦你开始了,它们的属性就一成不变了。当我们想要基于初始 from
/velocity
状态启动动画时非常适合,但如果我们想要持续交互则不是那么好。
physics
相反,它是一种 更接近视频游戏的集成模拟。它的工作原理是,每帧一次,获取当前状态,然后根据该时间点的当前属性对其进行修改。
这允许它是 mutable,这意味着我们可以更改这些属性,然后更改模拟的结果。
为了证明这一点,让我们对经典的指针平滑进行扭曲,使用弹性平滑。
进口 physics
:
const { pointer, spring, physics, styler, value } = popmotion;
这一次,我们要改变 startTracking
功能。我们将使用 , 而不是更改 ballXY
with :pointer
physics
const startTracking = () => { const physicsAnimation = physics({ from: ballXY.get(), to: ballXY.get(), velocity: ballXY.getVelocity(), restSpeed: false, friction: 0.6, springStrength: 400 }).start(ballXY); };
在这里,我们正在设置 from
和 velocity
正常。 friction
并且 springStrength
都调整了弹簧的属性。
restSpeed: false
覆盖运动停止时动画停止的默认行为。我们想手动停止它 stopTracking
。
就其本身而言,这个动画不会做任何事情,因为我们将 to
弹簧的目标 设置为与 相同 from
。所以 pointer
这次让我们重新实现跟踪来改变 physics
. 在 的最后一行 startTracking
,添加:
pointerTracker = pointer(ballXY.get()).start((v) => { physicsAnimation.setSpringTarget(v); });
在这里,我们使用与 pointer
以前类似的动画。除了这一次,我们用它来改变另一个动画的目标。为此,我们创建了这个弹性指针跟踪:
结论
基于速度的动画与指针跟踪配对可以创建引人入胜且有趣的界面。
spring
可用于创建各种弹簧感觉,同时 decay
专为动量滚动动画量身定制。 physics
在可配置性方面比任何一种都更有限,但也提供了改变正在进行的模拟的机会,开辟了新的交互可能性。
- spring
- decay
- physics