Animation & Screen

Frames as Sequences

An animation is a sequence of scenes — one map per frame. No timeline, no keyframes, no mutation:

(require '[eido.animate :as anim])

(def frames
  (anim/frames 60
    (fn [t]   ;; t goes from 0.0 to 1.0
      {:image/size [400 400]
       :image/background [:color/rgb 30 30 40]
       :image/nodes
       [{:node/type     :shape/circle
         :circle/center [200 200]
         :circle/radius (* 150 t)
         :style/fill    [:color/hsl (* 360 t) 0.8 0.5]}]})))
Rendered output

60 frames = 60 maps in a vector. Each frame is an independent scene — no shared mutable state between frames.

Easing and Helpers

The animation helpers shape how values change over time:

;; Sine pulse — 0→1→0 over the cycle
(anim/pulse t)

;; Linear fade — 1→0
(anim/fade-linear t)

;; Quadratic fade — softer tail
(anim/fade-out t)

;; Quadratic ease-in
(anim/fade-in t)

Combine these with your own math. Since t is just a number, any function works.

GIF Export

;; Animated GIF — loops by default
(eido/render frames {:output "anim.gif" :fps 30})

;; Non-looping GIF
(eido/render frames {:output "anim.gif" :fps 30 :loop false})

;; Higher resolution
(eido/render frames {:output "anim.gif" :fps 30 :scale 2})

Animated SVG

;; Animated SVG using SMIL
(eido/render frames {:output "anim.svg" :fps 30})

;; Or get the SVG string directly
(eido/render frames {:format :svg :fps 30})

Animated SVGs are resolution-independent and work in modern browsers.

PNG Sequence

For video production, render a numbered PNG sequence and encode with ffmpeg:

;; Write frame-0000.png through frame-0059.png
(eido/render frames {:output "frames/" :fps 30})

;; Then encode:
;; ffmpeg -framerate 30 -i frames/frame-%04d.png -c:v libx264 -pix_fmt yuv420p out.mp4

Seamless Loops

Use 4D noise for seamless looping — sample a circle in the noise space:

(require '[eido.gen.noise :as noise])

;; Seamless 1-second loop at 30fps
(anim/frames 30
  (fn [t]
    (let [angle (* 2 Math/PI t)
          nx    (Math/cos angle)
          ny    (Math/sin angle)]
      ;; perlin4d produces values that loop seamlessly
      ;; as (nx, ny) trace a circle
      (make-scene (noise/perlin4d x y nx ny)))))

perlin4d is specifically designed for this — the cos/sin trick traces a circle in the 3rd and 4th dimensions, producing a seamless loop in the first two.