# svg-animate **svg-animate** turns your TikZ diagrams into step-by-step animations that run natively in any web browser — no JavaScript, no plugins, no PDF viewer required. Write your diagram once. Get two outputs from the same source file: - an **animated SVG** for the web, embedded slides, or GitHub README previews - a **static PDF** for print, with all steps stacked or collapsed to a single clean frame The animation model maps directly onto the way you already think about progressive diagram reveals: - **`\begin{animate}`** — wraps your TikZ picture - **`\reveal{...}`** — marks what appears at the current step - **`\animstep`** — advances to the next step That is all you need for a working animation. Fine-grained control is there when you need it: per-step durations, multi-step and range visibility, blinking elements, one-shot or looping playback, and a `\noanimate` fallback that controls what a PDF reader shows after the animation ends. A LaTeX package for producing **animated SVG diagrams** with TikZ. The animation model is simple: content is divided into discrete *steps*, and only one step is fully visible at a time — like frames in a film. Opacity transitions are instantaneous (no cross-fades), implemented as SMIL keyframes in the SVG output. ## Quick start ```latex \documentclass{standalone} \usepackage{svg-animate} \begin{document} \begin{tikzpicture} \begin{animate}[duration=1] \reveal{\node at (0,0) {Step 1};} \animstep \reveal{\node at (0,0) {Step 2};} \animstep \reveal{\node at (0,0) {Step 3};} \end{animate} \end{tikzpicture} \end{document} ``` ## Compilation ```bash # Animated SVG latex diagram.tex && latex diagram.tex dvisvgm --font-format=woff2 --optimize=all --bbox=min diagram.dvi -o diagram.svg # Static PDF (animations ignored) xelatex diagram.tex ``` Or simply run `make` inside the package directory to build `example.svg` and `doc.pdf`. ## Example — traffic light The included `example.tex` animates a traffic light. Each coloured circle is its own step; the amber light uses a shorter `duration`. ![Traffic light animation](example.svg) > Open `example.svg` directly in a browser to see the animation. > GitHub's Markdown renderer may display it as a static image. ## Feature showcase The `test.tex` file exercises the main features side by side: ![Feature showcase](test.svg) | Column | Setting | What it shows | |---|---|---| | **loop=true** | default | loops indefinitely | | **loop=false** | `loop=false` + `\noanimate` | plays once, reverts to a static resting state | | **static** | `inactive opacity=1` | all steps visible simultaneously | Labels beside each light illustrate: - **fr. 1** — standard `\reveal`, active only in step 1 - **fr. 2+4** / **fr. 3+4** — `step={2,4}` / `step={3,4}`, active in multiple non-consecutive steps - **fr. 3 — blink** — `blink=0.3`, flashes during step 3; hidden between steps (default `blink off opacity=0`) - **fr. 3 — dimmed blink** — `blink=0.3, inactive opacity=0, blink off opacity=0.25`, hidden between steps; blinks between 1 and 0.25 during step 3 - **step={1-3}** — range syntax, active in steps 1 through 3 - **step={1,2,3,4}** — always visible, active in every step ## Static PDF output In PDF mode (`xelatex`, `pdflatex`) the package detects the output format and adapts automatically: - **No `\noanimate`** — `\reveal` elements are drawn at full opacity simultaneously (all steps stacked), which is useful for a quick overview. - **`\noanimate{content}` present** — `\reveal` elements are suppressed and only the `\noanimate` content is drawn, giving a single clean static frame. - **`\reveal[noanimate]{content}`** — forces this specific element to render in PDF even when `\noanimate` is active in the same environment. `\noanimate` is completely ignored in SVG mode. ## Key interface | Level | Syntax | Scope | |---|---|---| | Global | `\tikzset{/anim/duration=2}` | all diagrams | | Environment | `\begin{animate}[duration=1, inactive opacity=0]` | this environment | | Step | `\animstep[duration=0.5]` | following step | | Element | `\reveal[inactive opacity=0.2]{...}` | this element | | Static fallback | `\noanimate{...}` | PDF only, SVG ignored | ### `/anim/.cd` keys | Key | Default | Description | |---|---|---| | `duration` | `2` | seconds per step | | `active opacity` | `1` | opacity when step is active | | `inactive opacity` | `0` | opacity when step is inactive (`0`=hidden, `>0`=dimmed) | | `loop` | `true` | `false` = play once and freeze on last frame | | `noanimate` | — | force this `\reveal` to render in PDF even when `\noanimate` is present | | `step=` | — | show element during specific steps (see below) | | `blink=` | — | blink at given period during the active step (see below) | | `blink on opacity` | `1` | opacity during blink "on" half-periods within the active step | | `blink off opacity` | `0` | opacity during blink "off" half-periods within the active step (between steps the element uses `inactive opacity`) | | `static` | — | render all `\reveal` at full opacity (no animation); shorthand for the "show all steps simultaneously" idiom | ### One-shot animation with `loop=false` By default animations loop indefinitely. Set `loop=false` to play through all steps once and freeze on the last frame: ```latex \begin{animate}[duration=1, loop=false] \reveal{\node {Step 1};} \animstep \reveal{\node {Step 2};} \animstep \reveal{\node {Step 3};} \end{animate} ``` The global default can be changed with `\tikzset{/anim/loop=false}`. When the animation ends, the SVG browser reverts each element to its base opacity (fully visible). If a `\noanimate` fallback is present it therefore becomes visible at that point, giving the diagram a natural static resting state after the animation completes. ### Multi-step visibility with `step=` By default `\reveal` makes an element visible only during the **current step**. The `step=` key overrides this: the element becomes visible during every step in the specification, regardless of where `\reveal` is placed. ```latex \begin{animate}[inactive opacity=0.08] \reveal[step={1,3}]{\node[red] at (4,1) {visible in steps 1 and 3};} \reveal[step=2-4]{ \node[blue] at (4,0) {visible in steps 2 through 4};} \reveal[step={1,3-5}]{\node at (4,-1) {steps 1, 3, 4, 5};} \end{animate} ``` **Syntax:** - Single step — `step=2` - Range — `step=2-5` (steps 2, 3, 4, 5) - List — `step={1,3}` (braces required when listing multiple values) - Mix — `step={1,3-5}` (braces required) Consecutive steps in the specification are automatically merged into one animation window (no redundant keyframe at the shared boundary). ### Blinking elements with `blink=` The `blink=` key makes an element flash on and off during its active step. The value is the **full blink period** in seconds: the element is visible for `period/2` seconds, hidden for `period/2` seconds, and repeats. ```latex \begin{animate}[duration=2, inactive opacity=0.15] \reveal{\node at (0,1) {Step 1 — static};} \animstep \reveal[blink=0.4]{\node[fill=yellow] at (0,0) {Step 2 — blinks};} \animstep \reveal{\node at (0,-1) {Step 3 — static};} \end{animate} ``` If the step duration is not an exact multiple of `period/2`, the last partial half-period is shown up to the step boundary. `blink=` and `step=` are mutually exclusive; when both are given, `blink=` takes priority. The blink amplitude is controlled via `blink on opacity` (default `1`) and `blink off opacity` (default `0`). These keys govern **only** the intra-step oscillation; between steps the element uses `inactive opacity` as normal. To hide a blink element between steps, set `inactive opacity=0` explicitly. Because the static column now uses `\begin{animate}[static]`, this does not affect the static display: ```latex %% Hidden between steps; blinks between 1 and 0.25 during step 2. \reveal[blink=0.4, inactive opacity=0, blink off opacity=0.25]{ \node[fill=yellow] at (0,0) {Step 2}; } ``` ### Static display with `static` To render all steps simultaneously at full opacity (for a printed handout or overview), use the `static` key on the `animate` environment: ```latex \begin{animate}[static] \stepOne \animstep \stepTwo \animstep \stepThree \end{animate} ``` All `\reveal` elements are drawn at their natural opacity regardless of `inactive opacity`, `blink on/off opacity`, or any other per-element setting. This is cleaner than setting four opacity keys to `1`. ## Requirements - PGF/TikZ ≥ 3.1.9 (for `\usetikzlibrary{animations}`) - `dvisvgm` ≥ 2.9 for SVG output - Any modern LaTeX distribution (TeX Live 2022+, MiKTeX 22+) ## Documentation ```bash make doc.pdf ``` Full documentation with key reference and examples: `svg-animate.pdf`. ## Copyright `svg-animate` is copyright 2026 Sébastien Gross and distributed under the terms of the GNU Affero General Public License v3.0 or later.