Cross-Platform SVG Tools with Spec Coverage, Limitations, and Release Notes
This table compares tools that support SVG import/export across Windows, macOS, Linux, Android, iOS, and web. It includes license type, estimated SVG spec coverage, limitations, GitHub links, and SVG-related release notes.
Tool
License Type
Platforms Supported
SVG Import (%)
SVG Export (%)
Import Limitations
Export Limitations
GitHub URL
SVG Release Notes URL
Figma
Commercial SaaS
Windows, macOS, Linux, Android, iOS, Web
75
70
No animation; filters stripped; external fonts/images ignored
Text may be outlined; no animation; effects flattened; no embedded fonts
title = "Open-source timeline+code vector animation tools (cross-platform) — SVG import/export only"
date = "2025-11-02"
[[tool]]
name = "Glaxnimate"
timeline_ui = true
scripting = "Expression-like parameters; JSON import/export"
platforms = "Linux; macOS; Windows"
license = "GPL"
github = "https://github.com/mbasaglia/glaxnimate"
site = "https://glaxnimate.org"
notes = "Vector-first timeline and layer editor; imports and exports SVG and Lottie/JSON; designed for programmatic workflows."
llm_notes = """
- Author prompts that produce SVGs structured for Glaxnimate: named layers, grouped vector parts, and anchor points positioned for rigging.
- Emit JSON/Lottie-aware vector generation guidance so exported SVGs convert to keyframeable shapes and paths without manual rework.
- Produce expression snippets or parameter maps for procedural motion (e.g., pathOffset, trim, morphable shapes) that Glaxnimate can interpret.
- Create batch import scripts to map external SVG layer names into Glaxnimate layer IDs and apply initial keyframes.
"""
[[tool]]
name = "Wick Editor"
timeline_ui = true
scripting = "JavaScript (in-editor)"
platforms = "Linux; macOS; Windows"
license = "MIT"
github = "https://github.com/Wicklets/wick-editor"
site = "https://www.wickeditor.com"
notes = "Browser-first editor with desktop/Electron builds; supports vector drawing and a timeline with inline JS; supports importing and exporting SVG assets for timeline-driven vector animation."
llm_notes = """
- Generate clean SVG vectors from prompts that target animation-friendly topology (separate closed paths for fill regions; simple stroke outlines).
- Produce SVG layer hierarchy and element IDs that map directly to timeline symbols and object instances.
- Create JS snippets that wire SVG elements to timeline events, symbol swaps, and parameterized transforms.
- Emit automated path simplification rules (tolerance, preserveCorners) and node reduction commands to reduce keyframe complexity.
- Generate Lint/QA checks for SVGs (missing viewBox, non-decimal transforms, embedded raster data) before import.
"""
[[tool]]
name = "Synfig Studio"
timeline_ui = true
scripting = "Python (extensions, batch processing)"
platforms = "Linux; macOS; Windows"
license = "GPL"
github = "https://github.com/synfig/synfig"
site = "https://www.synfig.org"
notes = "Vector tweening engine with timeline/keyframe workflow and parametric vector objects; supports importing SVGs and working with vector parts for animation workflows."
llm_notes = """
- Generate decomposed vector part plans from character prompts (head/torso/limbs/controls) with anchor placement optimized for Synfig bones and switches.
- Autogenerate Synfig .sif scene templates with prewired layers, parameters, and named bones ready for procedural animation.
- Produce Python scripts to retime vector parameters, bake motion from high-level easing descriptions, and convert AI SVGs into Synfig layer groups.
- Recommend path interpolation strategies (compatible with Synfig's spline handling) and vector clean-up rules to avoid undesirable tween artefacts.
"""
Animation
Example
<svg width="200" height="400" xmlns="http://www.w3.org/2000/svg">
<!-- Head -->
<circle cx="100" cy="50" r="30" stroke="black" stroke-width="2" fill="none" />
<!-- Body -->
<line x1="100" y1="80" x2="100" y2="200" stroke="black" stroke-width="2" />
<!-- Left Arm -->
<line x1="100" y1="120" x2="60" y2="150" stroke="black" stroke-width="2" />
<!-- Right Arm (Animated) -->
<line x1="100" y1="120" x2="140" y2="150" stroke="black" stroke-width="2">
<animateTransform
attributeName="transform"
attributeType="XML"
type="rotate"
from="270 100 120"
to="-30 100 120"
dur="1s"
repeatCount="indefinite"
begin="0s"
fill="freeze"
/>
</line>
<!-- Left Leg -->
<line x1="100" y1="200" x2="70" y2="300" stroke="black" stroke-width="2" />
<!-- Right Leg -->
<line x1="100" y1="200" x2="130" y2="300" stroke="black" stroke-width="2" />
</svg>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>SVG Text Validation with handleEvent</title>
<style>
body {
font-family: sans-serif;
}
svg {
border: 1px solid #ccc;
display: block;
margin: 20px auto;
}
</style>
</head>
<body>
<svg width="500" height="200">
<!-- Draw a border rectangle -->
<rect x="10" y="10" width="480" height="180" fill="none" stroke="#000" />
<!-- Editable text element -->
<text id="editableText" x="20" y="50" font-size="20" fill="black">
Click to edit me
</text>
<!-- Validation message text element (hidden by default) -->
<text id="validationMsg" x="20" y="100" font-size="16" fill="red" visibility="hidden"></text>
</svg>
<script>
// Get references to SVG elements.
const textElement = document.getElementById('editableText');
const validationMsg = document.getElementById('validationMsg');
// The text node contained in <text>. (Assuming a single direct text node.)
const textNode = textElement.firstChild;
// Create an event handler object that implements handleEvent.
const validationHandler = {
handleEvent: function(event) {
// Retrieve the updated text.
const newText = textNode.nodeValue;
// Validation: input text must be at least 5 characters long.
if (newText.length < 5) {
textElement.setAttribute('fill', 'red');
validationMsg.textContent = 'Text must be at least 5 characters long.';
validationMsg.setAttribute('visibility', 'visible');
} else {
textElement.setAttribute('fill', 'green');
validationMsg.textContent = '';
validationMsg.setAttribute('visibility', 'hidden');
}
}
};
// Attach the event handler to the text node for DOMCharacterDataModified.
// Note: Although DOM mutation events are deprecated in favor of MutationObserver,
// we use them here per your request.
textNode.addEventListener('DOMCharacterDataModified', validationHandler, false);
// Set up a click event to simulate text editing.
textElement.addEventListener('click', function() {
// Prompt the user for new text.
const newText = prompt('Edit the text:', textNode.nodeValue);
if (newText !== null) {
// Directly update the text node; this change will trigger the mutation event.
textNode.nodeValue = newText;
}
});
</script>
</body>
</html>
SVG Scaling Stylesheet
To multiply or divide all dimensions by a variable, use this stylesheet