Animation Overview
AraraJS’s execution model is supposed to be minimal, powerful and flexible. Some of it’s features include:
- 🐦️ Frame-based animation loop with precise timing control
 - 🐦️ Composable animation callbacks for complex behaviors
 - 🐦️ Smart state management with automatic cleanup
 - 🐦️ Server-side rendering compatible
 
Bare Metal API Section titled Bare Metal API
The animation system is built around some basic building blocks:
- Animation Callbacks - Just a function that is called on each frame.
 - Animation Controller - Manages the animation loop and timing.
 
These basic building blocks don’t output a signal for you, they just manage timing and possibly orchestration of your animations.
Body Animations Section titled Body Animations
To get an output signal in a more convenient way, you may want to create a Body animation. Maybe you are not interested in how your signal change, which is the concept of velocity, but keep in mind that both velocity and acceleration are present in the Body object returned by the signal in case you need them in some point.
Maybe you won’t use them all, but the primitives come with them.
Composition and Other Primitives Section titled Composition and Other Primitives
Some common body animation primitives, like spring and sine wave, are available to you by the library. They come both in the form of just a callback, a BodyAnimationPass, which is a callback that applies changes to the body on every frame, and they also come in more convenient createSpring, createSine, … variants.
const [sine] = createSineWave()
// is equivalent to
const [sine] = createBodyAnimation(() => [
  sineWavePass()
])import { cn } from '@lib/cn'
import { createElementSize } from '@solid-primitives/resize-observer'
import { createSignal } from 'solid-js'
import { createSineWave } from 'ararajs'
export function SineWaveDemo(props: {
  class?: string
  ballClass?: string
  frequency?: () => number
}) {
  const [body] = createSineWave(() => ({
    amplitude: 90,
    frequency: props.frequency?.() ?? 1,
  }))
  const [container, setContainer] = createSignal<HTMLDivElement>()
  const containerSize = createElementSize(container)
  const [ball, setBall] = createSignal<HTMLDivElement>()
  const ballSize = createElementSize(ball)
  const xOffset = () => {
    return (
      body.position +
      -(ballSize.width ?? 0) / 2 +
      (containerSize.width ?? 0) / 2
    )
  }
  return (
    <div
      class={cn(
        'w-full overflow-hidden rounded-lg p-8 shadow-inner',
        props.class,
      )}
      ref={setContainer}
    >
      <div
        class={cn(
          'size-8 rounded-full bg-arara-text/70 shadow-xl',
          props.ballClass,
        )}
        style={{
          transform: `translate(${xOffset()}px`,
        }}
        ref={setBall}
      />
    </div>
  )
}Using the BodyAnimationPass will give you more flexibility because you can input multiple passes in a createBodyAnimation and these passes are applied in order. It’s easy to combine multiple Sines and Springs with that, which gives you easings and periodic behaviours.