Skip to content

[WIP] Animation Utilities#177

Open
lucasdinonolte wants to merge 3 commits into
mainfrom
animation-utils
Open

[WIP] Animation Utilities#177
lucasdinonolte wants to merge 3 commits into
mainfrom
animation-utils

Conversation

@lucasdinonolte

@lucasdinonolte lucasdinonolte commented May 17, 2023

Copy link
Copy Markdown
Contributor

This is a little something that was in the back of my head for some time – but it's only for after the new animation API is in.

Context

I've found myself copy & pasting over code to handle non-linear interpolation (aka easing) for animation over and over again. So I had this idea it could be cool if mechanic provided a simple way to use the most common easing functions without having to re-code them yourself.

What this does

This adds a @mechanic-design/transition package that exposes a generic interpolation helper to the user. It also comes with pre-built versions of the most commonly used easing functions for quick access. But users’ can also bring their own easing function if they wanted to.

The transition function is setup as a curried function, to encourage a clean usage based on animation lifecycle events—the transition should be set up when setting up your design function and then in the draw loop you only pull values from it.

Examples

The most basic example, animating a rectangle’s position:

import { transition } from "@mechanic-design/transition";

export const handler = async ({ inputs, frame, done, getCanvas, drawLoop }) => {
  const { width, height } = inputs;

  const { ctx } = getCanvas(width, height);
  const xPos = transition({
    from: width * 0.3,
    to: width * 0.7,
    duration: 2,

    // Allows to set how often the transition should run
    // Defaults to 1
    iterationCount: 10,

    // Defines the direction of the animation
    // forward (0 -> 1)
    // runs the animation in the specified direction
    //
    // reverse (1 -> 0)
    // runs the animation in the reversed direction 
    //
    // alternate (0 -> 1 -> 0 -> 1 -> ...)
    // runs the animation in alternating directions, starting
    // with a forwards run.
    //
    // alternateReverse (1 -> 0 -> -> 0 -> ...)
    // runs the animation in alternating directions, starting
    // with a reversed run.
    //
    // Defaults to forward
    direction: 'alternate',

    // A user can go for one of the pre-built easing functions
    // by referencing its name
    easing: 'easeInOutQuad',
  });

  drawLoop(({ timestamp }) => {
    ctx.clearRect(0, 0, width, height);

    ctx.fillStyle = "blue";
    ctx.fillRect(xPos(timestamp), height / 2 - 50, 100, 100);

    if (timestamp < 2) {
      frame();
    } else {
      done();
    }
  });
};

Using a custom easing function:

import { transition } from "@mechanic-design/transition";

export const handler = async ({ inputs, frame, done, getCanvas, drawLoop }) => {
  const { width, height } = inputs;

  const { ctx } = getCanvas(width, height);
  const xPos = transition({
    from: width * 0.3,
    to: width * 0.7,
    duration: 2,

    // Easing functions are called with a linear t value below 0 and 1
    // and map this value to whatever easing curve you want to approximate
    //
    // The example below maps to a cubic curve
    easing: t => t * t * t
  });

  drawLoop(({ timestamp }) => {
    ctx.clearRect(0, 0, width, height);

    ctx.fillStyle = "blue";
    ctx.fillRect(xPos(timestamp), height / 2 - 50, 100, 100);

    if (timestamp < 2) {
      frame();
    } else {
      done();
    }
  });
};

The transition helper only works with numerical values. You could however still use it to interpolate non numerical values (like color), by using the transition helper to generate the easing curve for you and then passing a normalized transition value to a specific interpolation function. The example shows this

const colorEase = transition({
    from: 0,
    to: 1,
    duration: 2,
    easing: 'easeInOutQuad',
});

drawLoop(({ timestamp }) => {
  // The imaginary colorInterpolator function would be a custom function
  // (user-written or from a library) that interpolates two colors based on
  // a 0–1 value. The transition helper is used here to put the easing curve
  // on the 0–1 scale.
  const color = colorInterpolator(color1, color2, colorEase);

  ctx.fillStyle = color;
});

@netlify

netlify Bot commented May 17, 2023

Copy link
Copy Markdown

Deploy Preview for dsi-logo-maker ready!

Name Link
🔨 Latest commit 564f6e5
🔍 Latest deploy log https://app.netlify.com/sites/dsi-logo-maker/deploys/64649e3d1d53df0008230470
😎 Deploy Preview https://deploy-preview-177--dsi-logo-maker.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site settings.

@lucasdinonolte lucasdinonolte changed the title Animation Utilities [WIP] Animation Utilities May 17, 2023
@fdoflorenzano
fdoflorenzano changed the base branch from main to new-animation-api May 17, 2023 14:53
Base automatically changed from new-animation-api to main November 17, 2025 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant