Learn

# Physics and velocity

A core feature of Popmotion is the ability for some animations (decay, spring and physics) to take a `velocity` parameter.

`velocity` changes each of these animations in a way that feels natural and visceral.

By passing the velocity of an existing animation to another, we can create natural-feeling transitions. And if that existing animation is `pointer`, it allows the user to directly affect animations with their own force leading to natural and playful interactions.

## Inspect velocity

But how do we get `velocity`?

Popmotion provides a special type of reaction called `value`.

``import { value } from 'popmotion';``

`value` sits between your action and another reaction (for instance a style setter), and can be queried with `get` and `getVelocity`:

``````const myValue = value(0, console.log);

tween().start(myValue);

setTimeout(() => myValue.getVelocity(), 100)``````

The returned `velocity` is measured in units per second. Why? Although 60fps is the current common framerate, VR devices support 90+ fps and the iPad Pro delivers a silky 120 frames per second!

To future-proof our code, we decouple velocity from the device framerate, otherwise our animations would run at 1.5x or even 2x the speed on these faster displays.

## Using `value`

`value` is provided two arguments: A value, and a function to call when this value updates:

``const foo = value(0, console.log);``

As `value` is a reaction, it has an `update` method. We can call it to update the value:

``foo.update(5);``

Usually though, we provide the `value` directly to an action:

``tween({ to: 5 }).start(foo);``

Like our animations, `value` can accept objects and arrays:

``````const xy = value({ x: 0, y: 0 }, console.log);
const foo = tween({
to: { x: 100, y: 200 }
}).start(xy);

setTimeout(() => xy.getVelocity(), 100); // Returns as object``````

Now we know enough about `value` to get the velocity of our user’s pointer.

## Get `pointer` velocity

Using the example from the previous tutorial, let’s first make a `value` that updates `ballStyler`‘s `x` and `y` properties:

``const ballXY = value({ x: 0, y: 0 }, ballStyler.set);``

Now we can replace our `startTracking` function with this:

``````const startTracking = () => {
pointer(ballXY.get()).start(ballXY);
};``````

As an added benefit of using `value`, a `value` can’t be subscribed to more than one action at a time.

This means that we can stop using `pointerTracker` to maintain a reference to our active `pointer`.

Instead, we can either use `ballXY.stop()`, which will stop the action it’s currently subscribed to. Or, we simply provide it to a different action, which is what we’ll do in the following examples.

For now, amend `stopTracking` so it queries `ballXY`‘s current velocity:

``````const stopTracking = () => {
const velocity = ballXY.getVelocity();
};``````

## Using `velocity`

Three Popmotion animations accept a `velocity` property: `decay`, `physics` and `spring`.

Let’s modify `stopTracking` three times, once for each, to see what they each do with `velocity`.

### `decay`

`decay` exponentially decreases a velocity over time. It’s a form of the algorithm used in smartphone momentum scrolling, making it a natural-feeling way of slowing something down.

Based on the initial properties and `velocity`, it’ll automatically calculate a `target` to animate to.

Using it is as easy as passing our newly-calculated `velocity` to `decay`:

``decay({ velocity }).start(ballXY);``

`decay` also accepts a `modifyTarget` function, which is provided the calculated target and returns a new one.

This can be used, for instance, to snap the target to a grid:

``````decay({
from: ballX.get(),
velocity,
modifyTarget: (target) => Math.ceil(target / 100) * 100
})``````

### `spring`

`spring` is a spring simulation using `mass`, `velocity`, `stiffness` and `damping`. It can be used to simulate a wide variety of spring-feels.

Springs are great for interaction designers because they’re expressive. For instance, you could design a spring that has a `stiffness` and `damping` property, but the `mass` property is based on the relative size of the element moving.

`spring` has defaults for all properties but you’ll likely want to adjust at least `stiffness` and `damping`:

``````spring({
from: ballXY.get(),
velocity,
stiffness: 300,
damping: 10
}).start(ballXY);``````

### `physics`

The `physics` animation is the swiss army knife of velocity-based animations.

It offers `friction`, `to` and `springStrength` properties, so it can theoretically be used to create motion similar to `decay` and `spring`.

However, `decay` and `spring` animations are differential equations that resolve for a given `elapsedTime`. In practical terms, this means that if you want to change the animation they’re creating, you need create a new animation with the new properties.

These equations are incredibly accurate, offering the smoothest motion and in the near future, will allow these animations to be scrubbable the same way `tween` is.

Instead, `physics` is an integrated simulation. This means that, once the simulation has started, its properties can be modified because `physics` uses its current state to calculate its next

For instance, we can tether a `physics` spring between the ball and the pointer:

``````const springTo = physics({
velocity: ballXY.getVelocity(),
friction: 0.6,
springStrength: 400,
to: ballXY.get(),
restSpeed: false
}).start(ballXY);

pointer(ballXY.get())
.start((v) => springTo.setSpringTarget(v));``````

## Conclusion

`velocity` is a key part of creating natural interactions with Popmotion.

Be sure to check out the full docs of value, decay, spring and physics, as there’s much more to each than we’ve been able to cover in this introductory tutorial.