Animated vector graphics for Rust
Animated SVG and Lottie in one Rust scene model.
dxn_vector_animation reads Figma Motion's animated SVG (CSS and SMIL), Lottie and dotLottie into one scene of groups, shapes and paints whose properties are keyframe tracks. Sample it into a display list, render it with the reference renderer, or play it: the NSH player maps the tracks onto NSH's native animation graph, so an animation runs on the UI thread on iOS, Android, macOS, Windows, Linux and the web.
[dependencies]
dxn_vector_animation = { git = "https://github.com/dXnSix/dXn.VectorAnimation", branch = "main" }
dxn_vector_animation_svg = { git = "https://github.com/dXnSix/dXn.VectorAnimation", branch = "main" }- Inputs
- SVG (CSS, SMIL), Lottie, dotLottie
- Rust
- 1.97+, edition 2024
- Core targets
- native and wasm32
- Player
- NSH, 7 platforms checked
- Unsafe
- forbidden
- License
- MIT OR Apache-2.0
What you get
What you get
Figma Motion's SVG
CSS @keyframes the way Figma Motion writes them, SMIL with begin and end times, events and accumulation, filters as effects, live text and patterns.
Read more →Lottie and dotLottie
Layers, shapes, shape modifiers, text with its animators, effects and layer styles, and expressions evaluated and baked into keyframes within a budget.
Read more →One scene model
Groups, shapes, images and text whose every property is a constant or a keyframe track on one timeline, so a player or a converter is written once.
Read more →Reference renderer and CLI
A tiny-skia renderer for golden tests and poster frames, and a vector-animation command that inspects, validates, compiles and renders files.
Read more →Native playback in NSH
The VectorAnimation component compiles a scene into canvases whose numbers NSH's animation graph moves on the UI thread, with no JavaScript per frame.
Read more →Bounded untrusted input
Every size, count, depth and expression step a file may take is bounded by Limits, and what a file holds that the scene leaves out is a warning.
Read more →Quick tour
#One model for two formats
An SVG and a Lottie file read into the same Scene: the importers differ, everything after them does not.
let svg = dxn_vector_animation_svg::read(&std::fs::read("loader.svg")?)?.scene;
let lottie = dxn_vector_animation_lottie::read(&std::fs::read("loader.json")?)?.scene;
for scene in [&svg, &lottie] {
let frame = scene.frame_at(scene.timeline.duration / 2.0);
println!("{} items half way", frame.items.len());
}
The scene’s nodes, paints and tracks are described in The scene model.
#Played on the UI thread
In an NSH app the VectorAnimation component plays a file natively. This is its web build, playing a Figma
Motion export:
import { VectorAnimation } from "dxn-vector-animation";
import button from "./button.vector-animation.json"; // compiled ahead with the CLI
<VectorAnimation src={button} style={{ width: 320, height: 160 }} paused={!active()} />
How a scene becomes canvases and graph nodes is in What it plays natively.
#Compile once, play anywhere
The CLI checks a file and compiles it into the scene format players load, with the importers out of the loop:
vector-animation validate --strict hero.svg
vector-animation compile hero.svg # hero.vector-animation.json
vector-animation render hero.svg --fps 30 --width 600
The commands and their flags are in The vector-animation CLI.
#Effects and masks, live
Drop and inner shadows, blurs, soft masks and color effects play on the graph where it can express them, and frame by frame where it cannot:
Every check scene is on the Examples page.