Learn

# Circular motion

HTML and SVG elements are positioned by `x` and `y` coordinates. This type of positioning is known as cartesian coordinates, and animating these is great for moving elements in straight lines (the majority use-case).

However, to move elements in a circular fashion, it’s much easier to animate position using polar coordinates: Position as defined by `angle` and `radius`.

We can then convert these polar coordinates into `x` and `y` to produce movement like this:

In this quick tutorial, we’ll create circular motion converting polar to cartesian coordinates using functional composition.

As a bonus step, we’ll then explain how we can rotate the element to face its direction of travel.

You can fork this CodePen to follow along.

## Position

We can convert `radius` and `angle` into `x` and `y` using `cos` and `sin` functions:

``````const x = radius * Math.cos(angle);
const y = radius * Math.sin(angle);``````

By expressing this as a pure function, we’ll be able to provide it to any animation’s `pipe` method:

``````const polarToCartesian = ({ angle, radius }) => ({
x: radius * Math.cos(angle),
y: radius * Math.sin(angle)
});``````

With this function we can write a simple animation that:

• 1) Changes `radius` at a constant velocity of 5 radians a second.
• 2) Pipes the animation output through `polarToCartesian` to convert into `x` and `y`.
• 3) Styles the div by using `boxStyler.set`:
``````physics({
from: { angle: 0, radius: 150 },
velocity: { angle: 5, radius: 0 }
}).pipe(polarToCartesian)
.start(boxStyler.set);``````

Now our box moves in a circular motion.

In this animation we’re keeping `radius` at a constant value by setting `velocity` to `0`. By using the `composite` function, we can combine two different animations to animate `radius` and `angle` in different ways:

``````composite({
angle: physics({ velocity: 5 }),
from: 0,
to: 150,
yoyo: Infinity,
ease: easing.easeInOut,
duration: 2000
})
}).pipe(polarToCartesian)
.start(boxStyler.set);``````

## Direction

It looks a little awkward to have a square stay upright as it moves in a circular motion.

We can calculate and inject a `rotate` property based on the current `angle` to ensure the square is facing the direction of travel.

First, let’s make our `polarToCartesian` function more composable by allowing it to pass through any properties that it doesn’t consume using spread props:

``````const polarToCartesian = ({ angle, radius, ...props }) => ({
x: radius * Math.cos(angle),
y: radius * Math.sin(angle),
...props
});``````

Next, we need to make a function that simply takes `angle` and returns the angle perpendicular to it as a new property, `rotate`.

`cos` and `sin` functions accept radians, whereas CSS and SVG `rotate` properties are defined in degrees. We can use Popmotion’s `radiansToDegrees` calculator to convert `angle` into degrees, and then simply rotate it by `90`:

``````const rotatePerpendicular = (props) => {
const { angle } = props;
return {
rotate: radiansToDegrees(angle) + 90,
...props
};
};``````

Applying this new function is as easy as modifying `pipe` to read:

``.pipe(rotatePerpendicular, polarToCartesian)``

## Conclusion

Circular motion is much easier to reason about in polar coordinates, and mapping these to cartesian is simple with `pipe`.

We can animate `angle` and `radius` with separate animations by using the `composite` composition function.

And finally, we can make the element rotate along with the direction of travel by converting `angle` into degrees and then adding an extra `90` degrees.