Experiments >

Animation commands

Experiment #56 ● 18th March, 2021 ● by Joshua Nussbaum

I’m redoing an experiment from last week that got lost because it wasn’t saved.

It’s funny how redoing things makes it so much better. It’s almost a good thing that I lost the work.

Animation logic

This is about figuring out how the animation code should be organized. The idea is that each command (append, insert, scroll, etc…) is a function that return a object with 3 keys start, stop and tween, each respresents a phase in animation:

function insert(editor, step) {
  return {
    start() {
      // stuff to do at the beginning of the step.
      // called once per step
    },
    stop() {
      // stuff to do at the end of the step.
      // called once per step.
    },
    tween(percentage) {
      // this is called repeatedly to tween the animation
      // the parameter is a value between 0 -> 1.0

      // NOTE: the parameter is not always linear,
      // it can move backwards depending on the easing function
    }
  }
}

Each phase (start, stop, tween) is optional. In fact the delay command implements none of them:

function delay() {
  return {}
}

Running a step

Each step executes in a infinite loop of setTimeout calls:

// import all easingFns as a dictionary
import * as easingFns from 'svelte/easing'

// create a tweened store, it's re-used for each step
const tween = tweened(0)

function next(index) {
  // get the current step
  const step = steps[index]
  // find the command based on step type, and initialize
  const command = command[step.type](editor, step)

  // invoke start logic (when applicable)
  if (command.start) command.start()

  if (command.tween) {
    // reset the tweened store
    tween.set(0, {duration: 0})

    // find the easing function
    const easing = easingFns[step.easing || 'linear']

    // subscribe to change
    tween.subscribe(val => command.tween(val))

    // trigger tweening
    tween.set(1, {duration, easing})
  }

  setTimeout(() => {
    // invoke stop logic (when applicable)
    if (command.stop) command.stop()

    // advance forward
    next(index + 1)
  }, duration)
}

Code

https://svelte.dev/repl/92d2b90946ca4333af4d00a8d7cb4e0a?version=3.35.0

view all experiments

Stay tuned in

Learn how to add more experimentation to your workflow