Turn a matplotlib figure and a per-frame update function into one self-contained, looping, animated SVG.
Why svganim
- A real image. One SVG file that works in an
<img>tag and in GitHub READMEs. No JavaScript, no HTML page, no player. - Vector. Sharp at any size, unlike a GIF.
- Only what changes is animated. Axes, labels and static data are written once, so files stay small.
- Reproducible. Same code and matplotlib version, same bytes.
What you give up: playback controls, and changes to the number of elements inside
an artist, such as text that grows (see Limitations). If you need those,
use HTMLWriter or to_jshtml.
Install
pip install svganim
Usage
import matplotlib.pyplot as plt
import numpy as np
from svganim import anim_to_svg
fig, ax = plt.subplots()
x = np.linspace(0, 2 * np.pi, 200)
(line,) = ax.plot(x, np.sin(x))
def update(i):
line.set_ydata(np.sin(x + i / 10))
anim_to_svg(fig, update, n_frames=60, fps=20, hold=1.0, path="wave.svg")
<img src="wave.svg" alt="A moving sine wave">
In Jupyter and Quarto, end a cell with the call and the animation is displayed,
also in the rendered HTML. Call plt.close(fig) first, or the notebook also
shows matplotlib's static figure.
update changes the artists (set_data, set_offsets, set_color, ...). A line
whose data grows is fine, so draw trails and curves with set_data on a single
line. Artists can also come and go: create them once and show or hide them with
set_visible.
anim_to_svg(fig, update, n_frames, fps=20, hold=1.0, path=None, *, precision=3, interpolate=False)
| Argument | Description |
|---|---|
fig |
The matplotlib figure to render. |
update |
Called as update(i) before frame i is rendered. |
n_frames |
Number of frames. |
fps |
Frames per second. |
hold |
Seconds to hold the last frame before looping. |
path |
If given, the SVG is also written to this file. |
precision |
Decimals kept in coordinates. Lower means smaller files. |
interpolate |
If True, shapes glide and colours fade between frames instead of switching. See the k-means example. |
Returns the SVG as a string. Raises ValueError if the figure breaks a rule
below; the message names the element that changed.
How it works
Each frame is rendered to SVG and the first one becomes the base document. Later frames are compared with it, and every attribute that changes gets a SMIL animation. Elements that never change are left untouched.
Limitations
- Artists can appear and disappear, but the number of SVG elements inside an
artist must stay the same: no text that changes length, no axis limits that
change the ticks, no
imshow. - There are no playback controls, only a loop.
Examples and docs
The documentation has a gallery of notebooks that explain each example, plus an API reference built from the docstrings. It also shows how animations display in Jupyter and Quarto.
Development
uv run pytest
# the browser tests render every frame in Chromium, and are skipped without it
uv run --group browser playwright install chromium-headless-shell
uv run --group browser pytest tests/test_browser.py
uv run sphinx-build -W docs docs/_build/html
License
MIT
Metadata
Release files for svganim 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| svganim-0.2.0.tar.gz | 12.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| svganim-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 27.4 kB
Release files / svganim-0.2.0.tar.gz
| Download URL | svganim-0.2.0.tar.gz |
|---|---|
| Size | 12.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
92dc5f21790e6391185e756e9a9827adf75e2f45808a3148b47a480b35a1a1ae
|
|
BLAKE2b-256 checksum How to use checksums |
d6f740d35c2a29cc688a0f56de056e6dd8b0a6057fb00d82658d06f62c4ca0a2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / svganim-0.2.0-py3-none-any.whl
| Download URL | svganim-0.2.0-py3-none-any.whl |
|---|---|
| Size | 15.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
71eaf19b05b2db2360c3403c9eb19b3e11b275e2c283ef9fb416e21a42ea354f
|
|
BLAKE2b-256 checksum How to use checksums |
8a196f0de77cd502e3c3504e578adfc9d072dec310c0ba0bdd5883bbd91a73c7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency log