Bounce easing

Matt Perry

In this tutorial, we're going to build the Bounce easing example step-by-step.

This example is rated intermediate difficulty, which means we'll spend some time explaining the Motion APIs we've chosen to use, but it assumes familiarity with JavaScript as a language.

Here's a live demo of the example we're going to be creating:

Loading...

Introduction

The Bounce easing example shows a toggle switch that animates a ball downwards with a gravity-esque bounce animation. It uses the animate function from Motion to create smooth animations with custom easing functions and spring physics.

This example demonstrates how to use custom easing functions alongside spring animations. The ease option allows you to define your own timing curves, while spring physics provides natural motion based on physical properties like stiffness and damping.

Get started

Let's start with the basic HTML structure and styles for our toggle switch:

<div class="container">
    <div class="switch">
        <div class="ball"></div>
    </div>
</div>

<script type="module">
    // We'll add our code here
</script>

<style>
    /** Copy styles from example source code */
</style>

The switch is a vertical container that will hold our animated ball. Notice the will-change: transform property on the ball - this tells the browser to optimize for transform animations.

Let's animate!

Import from Motion

First, import the animate function from Motion:

import { animate } from "motion"

Creating a custom easing function

Before we add interactivity, let's create our custom bounce easing function. This function takes a progress value between 0 and 1 and returns an eased value:

// From https://easings.net/#easeOutBounce
function bounceEase(x) {
    const n1 = 7.5625
    const d1 = 2.75

    if (x < 1 / d1) {
        return n1 * x * x
    } else if (x < 2 / d1) {
        return n1 * (x -= 1.5 / d1) * x + 0.75
    } else if (x < 2.5 / d1) {
        return n1 * (x -= 2.25 / d1) * x + 0.9375
    } else {
        return n1 * (x -= 2.625 / d1) * x + 0.984375
    }
}

This easing function creates a bouncing effect by calculating different quadratic curves for different parts of the animation. The constants n1 and d1 control the bounce intensity and timing.

Defining animation options

Now let's create two different animation configurations - one for bouncing and one for spring physics:

const bounce = {
    duration: 1.2,
    ease: bounceEase,
}

const spring = {
    type: "spring",
    stiffness: 700,
    damping: 30,
}

The bounce configuration uses our custom easing function with a duration of 1.2 seconds. The spring configuration creates physics-based motion with high stiffness (700) for snappy movement and moderate damping (30) to control oscillation.

Adding interactivity

Now let's make the switch interactive by tracking state and listening for clicks:

const ball = document.querySelector(".ball")
const switchEl = document.querySelector(".switch")
let isOn = true

switchEl.addEventListener("click", () => {
    isOn = !isOn

    animate(ball, { y: isOn ? 0 : 120 }, isOn ? spring : bounce)
})

We track the toggle state with isOn, then flip it on each click. The ball animates to y: 0 (top position) when on, and y: 120 (bottom position) when off.

Here's the clever part: when turning on (moving up), we use the spring animation for a snappy return. When turning off (moving down), we use the custom bounce easing for a playful falling effect. This creates an asymmetric animation that feels natural - things fall with gravity and bounce, but spring back up quickly.

Conclusion

We've built a toggle switch that demonstrates the flexibility of Motion's animation system. By combining custom easing functions with spring physics, we created animations that feel both playful and natural. The animate function makes it easy to switch between different animation styles dynamically, letting you craft unique motion for different interactions.

Motion is supported by the best in the industry.