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]}]})))
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 (:fps default 12)
(eido/render frames {:output "anim.gif" :fps 30})A sequence of frames renders to an animated GIF. Render the same frames without :output to get the encoded GIF bytes back as a value.
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.