Experiments >

Animation commands

Experiment #5618th March, 2021by 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