dinamika-core 0.1.0

Declarative animation library: flex-based shapes, reactive signals, and a timeline (pause/parallel/sequence) on top of the dinamika-cpu raster renderer.
Documentation
  • Coverage
  • 72.28%
    73 out of 101 items documented10 out of 10 items with examples
  • Size
  • Source code size: 273.33 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 3.32 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 8s Average build duration of successful builds.
  • all releases: 8s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • aviancode/dinamika
    3 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • aviancode

dinamika-core

A declarative animation library built on top of the dinamika-cpu raster renderer. In the spirit of Motion Canvas: a scene of flex-laid-out shapes whose properties are reactive signals, animated on a timeline and rendered to PNG frames.

It consists of three parts:

  • Shapes (Shape) — scene nodes with CSS-like flex layout and signal-backed properties.
  • Signals (Signal, Computed) — reactive values that can be read, written and animated.
  • Timeline (Timeline) — composition of animations over time: pause, parallel and sequence/cascade.

Features

  • Shapes — rectangle (Shape::rect), circle/ellipse (Shape::circle), a backgroundless layout container (Shape::layout), text (Shape::text) and code (Shape::code).
  • Flex layoutDirection, Justify, Align, gap, per-side padding (with CSS-like shorthands), children, and sizes as a Length (pixels or a percentage of the parent) with min/max bounds.
  • Animatable properties — position, size, background, corner radius, opacity, rotation, scale, gap and padding. Each setter sets the value immediately and returns a handle; append .over(duration, easing) to animate.
  • Text — CSS-like style (font, font size, color, alignment, letter spacing, line height), content edits (spawn/typing/smoothing) and range highlighting.
  • Code — the same text, but colored per-character by syntax highlighting via a manually configured Palette and a Language (powered by syntect).
  • Easing — a full set of curves (Quad/Cubic/Quart/Sine/Expo/ Back/Bounce/Elastic, each in In/Out/InOut).
  • Timelinepause, parallel, sequence and cascade; a registered shape's single animation can be added as a plain expression.
  • Output — render the whole animation to numbered PNG frames, directly or via the scene_dir!/render! macros.

Architecture

Module Purpose
easing interpolation curves (Easing)
signal reactive values (Signal, Computed, Tweenable)
shape scene nodes, flex layout, text and code
timeline composition of animations over time and scene sampling
render two-pass flex layout and rasterization onto a Pixmap
output saving frames to PNG (render, scene_dir!/render!)

The renderer is re-exported as dinamika_core::cpu, with frequently used types (Color, Pixmap, Paint, Transform, gradients, …) lifted to the crate root.

Example

use dinamika_core::*;

// The timeline is created first (interior mutability — no `mut`).
let tl = Timeline::new(320, 160, Color::from_rgba8(20, 20, 24, 255), 30.0);

// Scene: a row container with two squares, registered on the timeline.
let a = Shape::rect().background(Color::from_rgba8(229, 192, 123, 255)).size(60.0, 60.0);
let b = Shape::rect().background(Color::from_rgba8(152, 195, 121, 255)).size(60.0, 60.0);
let _row = Shape::rect()
    .at(20.0, 20.0)
    .background(Color::from_rgba8(40, 44, 52, 255))
    .radius(12.0)
    .direction(Direction::Row)
    .gap(20.0)
    .padding(20.0)
    .align(Align::Center)
    .child(a.clone())
    .child(b.clone())
    .on(&tl);

// Move and recolor in parallel, wait, then a sequence of opacities.
tl.parallel(vec![
    a.rotation(180.0).over(1.0, Easing::CubicInOut),
    b.background(Color::from_rgba8(97, 175, 239, 255)).over(1.0, Easing::Linear),
]);
tl.pause(0.25);
tl.sequence(vec![
    a.opacity(0.2).over(0.5, Easing::QuadOut),
    b.opacity(0.2).over(0.5, Easing::QuadOut),
]);

// A single frame (RGBA, premultiplied alpha)…
let frame = tl.frame(0.5);
assert_eq!(frame.width(), 320);

// …or render the whole animation to PNG frames.
tl.render("outputs/demo").unwrap();

Set a value or animate it

Each animatable property has one setter that takes a value. It applies the value immediately and returns a lightweight handle that dereferences back into the Shape, so the builder chain keeps flowing. The same setter, with .over(...), builds a tween for the timeline:

use dinamika_core::*;

let card = Shape::rect().at(40.0, 40.0).size(320.0, 120.0);

// Set now:
card.background(Color::from_rgba8(40, 44, 52, 255)).radius(16.0);

// Animate (on the timeline):
let _move = card.x(120.0).over(1.0, Easing::CubicInOut);

Code with syntax highlighting

use dinamika_core::*;

let bytes = std::fs::read("Consolas.ttf").unwrap();
let snippet = Shape::code("fn main() {\n    println!(\"hi\");\n}")
    .font(bytes)
    .font_size(28.0)
    .language(Language::Rust)
    .palette(
        Palette::new(Color::from_rgba8(212, 212, 212, 255))
            .keyword(Color::from_rgba8(197, 134, 192, 255))
            .string(Color::from_rgba8(206, 145, 120, 255))
            .number(Color::from_rgba8(181, 206, 168, 255)),
    );

The demonstration scene can be rendered with the command:

cargo run -p dinamika