NexusCS

SVG.js

JavaScript
SVG.js is a lightweight JavaScript library for manipulating and animating SVG elements. Quick reference for shapes, transforms, animations, and DOM operations.
svg
graphics
animation
dom

Getting started

Installation

# NPM
npm install @svgdotjs/svg.js

Import

// ES6 Import
import { SVG } from "@svgdotjs/svg.js";

// CDN
<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/svg.js@3.0/dist/svg.min.js"></script>;

Quick Example

// Initialize drawing
const draw = SVG().addTo("#container").size(300, 300);

// Create shapes
draw.rect(100, 100).move(50, 50).fill("#f06");
draw.circle(100).move(200, 50).fill("#0f6");
draw.text("Hello SVG.js").move(50, 200);

Basic Shapes

Rectangle

// Basic rectangle
draw.rect(100, 100).move(50, 50).fill("#f06");

// Rounded corners
draw.rect(100, 100).radius(10);

// Square (single dimension)
draw.rect(100);

Circle & Ellipse

// Circle (diameter)
draw.circle(100).move(200, 50);

// Ellipse (width, height)
draw.ellipse(200, 100).center(300, 100);

// Circle by radius
draw.circle(100).radius(50);

Line & Polyline

// Line
draw.line(0, 0, 100, 150).stroke({ width: 1, color: "#000" });

// Polyline (open)
draw.polyline("0,0 100,50 50,100");
draw.polyline([
  [0, 0],
  [100, 50],
  [50, 100],
]);

// Polygon (closed)
draw.polygon("0,0 100,50 50,100");

Path

// SVG path notation
draw.path("M0 0 H50 A20 20 0 1 0 100 50 v25 C50 125 0 85 0 85 z");

// Update path
path.plot("M10 80 C 40 10, 65 10, 95 80");

// Path metrics
path.length(); // Total length
path.pointAt(105); // => { x, y }
path.array(); // => PathArray

Attributes & Styling

Attributes

// Set single attribute
rect.attr("x", 50);

// Set multiple
rect.attr({
  fill: "#f06",
  stroke: "#000",
});

// Get attribute
rect.attr("x"); // => 50

Fill & Stroke

// Fill with opacity
rect.fill({ color: "#f06", opacity: 0.6 });
rect.fill("#f06"); // Color only

// Stroke
rect.stroke({
  color: "#000",
  width: 5,
  linecap: "round",
  linejoin: "miter",
});

// Opacity
rect.opacity(0.5);

CSS & Classes

// CSS property
rect.css("cursor", "pointer");
rect.css({
  cursor: "pointer",
  "user-select": "none",
});

// Classes
rect.addClass("active");
rect.removeClass("active");
rect.toggleClass("active");
rect.hasClass("active"); // => boolean
rect.classes(); // => array

Visibility

rect.hide(); // display: none
rect.show(); // display: block
rect.visible(); // => boolean

rect.opacity(0); // Transparent but present

Positioning & Sizing

Absolute Positioning

// By top-left corner
rect.move(200, 350);
rect.x(200); // X only
rect.y(350); // Y only

// By center
rect.center(150, 150);
rect.cx(200); // Center X
rect.cy(350); // Center Y

Relative Positioning

// Delta move
rect.dmove(10, 30); // Relative delta
rect.dx(10); // Delta X
rect.dy(30); // Delta Y

// From current position
rect.dmove(-20, 50);

Sizing

// Set width and height
rect.size(200, 300);
rect.width(200); // Width only
rect.height(300); // Height only

// Proportional resize
rect.size(200); // Keeps aspect ratio

Transforms

Basic Transforms

// Rotate (degrees)
rect.rotate(45);
rect.rotate(45, 50, 50); // With center

// Scale
rect.scale(2); // Uniform
rect.scale(0.5, 1.5); // X, Y

// Translate
rect.translate(50, 100);

// Skew
rect.skew(0, 45);

// Flip
rect.flip("x"); // or 'y', 'both'

Complex Transforms

// Combined transform
rect.transform({
  rotate: 125,
  translateX: 50,
  translateY: 100,
  scale: 3,
  origin: "center", // or 'top left', [x, y]
});

// Relative transform
rect.transform({ rotate: 125 });
rect.transform({ rotate: 37.5 }, true);

Transform Queries

// Get transform object
rect.transform();
// => { translateX, translateY, scaleX, scaleY, rotate, ... }

// Get specific value
rect.transform("rotate"); // => 125
rect.transform("scale"); // => 3

Text

Simple Text

// Text with newlines
draw.text("Hello world.\nSecond line.");

// Plain text (no processing)
draw.plain("No line processing");

// Update text
text.text("New content");
text.clear(); // Remove text

Text Builder

// Builder pattern
draw.text(function (add) {
  add.tspan("Bold text ").newLine();
  add.tspan("colored").fill("#f06");
  add.tspan(" end.");
  add.tspan("New line").newLine().dx(20);
});

// Text length
text.length(); // Computed length

Font Settings

text.font({
  family: "Helvetica",
  size: 144,
  anchor: "middle", // start, middle, end
  leading: "1.5em",
  weight: "bold",
  style: "italic",
});

// Line height
text.leading(1.3);

// Individual properties
text.font("size", 20);

Text on Path

const path = draw.path("M0 80 C 40 10, 65 10, 95 80");
path.text("SVG.js rocks!");

// Update path
path.plot("M10 80 Q 95 10 180 80");

Animation

Basic Animation

// Duration, delay, when
rect.animate(2000, 1000, "now").move(150, 150);

// Chain animations
rect.animate().fill("#f03").animate().move(100, 100);

// Animate multiple properties
rect.animate(500).attr({
  fill: "#f03",
  opacity: 0.5,
});

Animation Config

rect
  .animate({
    duration: 2000,
    delay: 1000,
    when: "now", // 'now' | 'absolute' | 'relative' | 'last' | 'after'
    swing: true, // Reverse animation
    times: 5, // Repeat count
    wait: 200, // Wait between repeats
  })
  .attr({ fill: "#f03" });

Easing

// Ease in-out
rect.animate().ease("<>").move(100, 100);

// Ease out
rect.animate().ease(">").move(100, 100);

// Ease in
rect.animate().ease("<").move(100, 100);

// Linear
rect.animate().ease("-").move(100, 100);

Loops & Callbacks

// Loop animation
rect.animate(500).move(100, 100).loop(5, true, 200);
// times, swing (reverse), wait

// During callback (every frame)
rect
  .animate()
  .move(100, 100)
  .during(function (pos) {
    // pos: 0 to 1
    this.fill({ opacity: pos });
  });

// After callback
rect
  .animate()
  .move(100, 100)
  .after(function () {
    this.fill("#f06");
  });

Timeline Control

const timeline = rect.timeline();

timeline.pause();
timeline.play();
timeline.stop(); // Stop and reset
timeline.reverse();
timeline.speed(2); // 2x speed
timeline.time(100); // Seek to time
timeline.finish(); // Jump to end

Shared Timeline

const timeline = new SVG.Timeline();

rect1.timeline(timeline);
rect2.timeline(timeline);

rect1.animate(300, 0, "absolute").move(300, 300);
rect2.animate(400, 200, "absolute").move(500, 500);

timeline.play();

Events

Event Methods

// Click handler
rect.click(function () {
  this.fill("#f06");
});

// Remove handler
rect.click(null);

// on/off
rect.on("click", function (event) {
  console.log(event);
});

rect.off("click", handler); // Remove specific
rect.off("click"); // Remove all click
rect.off(); // Remove all

Multiple Events

// Multiple event types
rect.on("click mouseover", handler);

// Namespaced events
rect.on("click.ns", handler);
rect.off(".ns"); // Remove namespace

// Event delegation
group.on("click", "rect", function () {
  // this = rect element
});

Custom Events

// Fire custom event
rect.on("myevent", function (e) {
  alert(e.detail.some);
});

rect.fire("myevent", { some: "data" });

// With native event
rect.fire(
  new CustomEvent("custom", {
    detail: { value: 42 },
  }),
);

Available Events

Event Description
click Mouse click
dblclick Double click
mousedown Mouse button down
mouseup Mouse button up
mouseover Mouse enters
mouseout Mouse leaves
mousemove Mouse moves
touchstart Touch begins
touchmove Touch moves
touchend Touch ends
touchcancel Touch canceled

Groups & Containers

Group

const group = draw.group();
group.rect(100, 100).fill("#f06");
group.circle(100).fill("#0f6");

// Transform group
group.move(50, 50);
group.rotate(45);

Nested SVG

// Nested SVG element
const nested = draw.nested();
nested.size(200, 200);
nested.rect(100, 100);

// Viewbox
nested.viewbox(0, 0, 100, 100);

Use & Link

// Reuse element
const original = draw.circle(100);
const use = draw.use(original).move(200, 200);

// Anchor link
const link = draw.link("https://svgjs.dev");
link.rect(100, 100);

Definitions

// Defs container
const defs = draw.defs()
const gradient = defs.gradient('linear', ...)

// Symbol (reusable)
const symbol = draw.symbol()
symbol.rect(100, 100)
const use = draw.use(symbol)

Gradients & Patterns

Linear Gradient

const gradient = draw.gradient("linear", function (add) {
  add.stop(0, "#333");
  add.stop(0.5, "#f03");
  add.stop(1, "#fff");
});

// Direction (0-1 coordinates)
gradient.from(0, 0).to(0, 1);

// Apply
rect.fill(gradient);

Radial Gradient

const radial = draw.gradient("radial", function (add) {
  add.stop(0, "#333");
  add.stop(0.5, "#f03");
  add.stop(1, "#fff");
});

// Position and radius
radial.from(0.5, 0.5).to(0.5, 0.5).radius(0.5);

rect.fill(radial);

Pattern

const pattern = draw.pattern(20, 20, function (add) {
  add.rect(20, 20).fill("#f06");
  add.rect(10, 10);
  add.circle(10).center(10, 10);
});

rect.fill(pattern);

// Update pattern
pattern.update(function (add) {
  add.circle(5);
});

Masking & Clipping

Masking

// Create mask
const ellipse = draw.ellipse(80, 40).fill("#fff");

// Apply mask
rect.maskWith(ellipse);

// Get mask
rect.masker(); // => SVG.Mask

// Remove mask
rect.unmask();

Clipping

// Create clip path
const circle = draw.circle(100);

// Apply clip
rect.clipWith(circle);

// Get clipper
rect.clipper(); // => SVG.ClipPath

// Remove clip
rect.unclip();

DOM Operations

Add & Remove

// Add child (returns parent)
group.add(rect);

// Add to parent (returns child)
rect.addTo(group);

// Put child (returns child)
group.put(rect);

// Put in parent (returns parent)
rect.putIn(group);

// Remove from DOM
rect.remove();

// Replace element
rect.replace(circle);

Clone & Reorder

// Deep clone
const clone = rect.clone();

// Reorder
rect.front(); // Move to front
rect.back(); // Move to back
rect.forward(); // One step forward
rect.backward(); // One step backward

Traversal

// Get parent
rect.parent(); // => SVG.G

// Get children
group.children(); // => array

// Get siblings
rect.siblings(); // => array

// CSS query
rect.find("rect.active"); // => array
rect.findOne("circle"); // First match

Data & Memory

DOM Data

// Store in DOM (survives reload)
rect.data("key", { value: 0.3 });

// Get data
rect.data("key"); // => { value: 0.3 }

// Remove data
rect.data("key", null);

// Get all
rect.data(); // => object

Memory Storage

// In-memory only
rect.remember("oldBBox", rect.bbox());

// Get
rect.remember("oldBBox"); // => bbox object

// Remove
rect.forget("oldBBox");

// Forget all
rect.forget();

Geometry

Bounding Box

// Untransformed box
element.bbox();
// => { x, y, width, height, cx, cy, x2, y2 }

// Transformed box (relative to document)
element.rbox();

// Relative to container
element.rbox(drawing);

// Point inside element
rect.inside(60, 70); // => boolean

Viewbox & Zoom

// Set viewbox
draw.viewbox(10, 10, 500, 600);

// Get viewbox
draw.viewbox(); // => { x, y, width, height }

// Zoom
draw.zoom(2); // 2x zoom

// Zoom to point
draw.zoom(2, { x: 20, y: 20 });

Import/Export

Export SVG

// Full SVG string
draw.svg();

// Element SVG
rect.svg();

// Children only
draw.svg(false);

// Get as string
const svgString = draw.svg();

Import SVG

// Import SVG string
draw.svg('<g><rect width="100" height="50" fill="#f06"></rect></g>');

// Clear and import
draw.clear().svg("<svg>...</svg>");

// Import overwrites
draw.svg('<circle r="50"/>');

Reference Existing

// From CSS selector
const el = SVG("#existingElement");

// From DOM node
const fromNode = SVG(domNode);

// Check if SVG.js element
el instanceof SVG.Element; // => true

Gotchas

  • ⚠️ v3.x uses ES6 importsimport { SVG } from '@svgdotjs/svg.js' required, global SVG no longer auto-available in module environments
  • ⚠️ move() vs translate()move() positions by top-left (absolute), translate() shifts relative; easy to confuse when chaining transforms
  • ⚠️ Path animation restrictions — Only paths with same commands are morphable; can't animate M L to M C without manual interpolation
  • ⚠️ data() vs remember()data() stores in DOM attributes (survives reload), remember() is in-memory only; not interchangeable
  • ⚠️ Animation queuing — Default when is 'after' not 'now'; animations queue by default unless you specify 'now' or 'absolute'
  • ⚠️ Size initialization — Must call .size() on SVG root; SVG.js doesn't auto-set viewBox or width/height
  • ⚠️ Text leading assumptionleading() assumes every first-level tspan is a new line; breaks with complex nested tspan structures
  • ⚠️ Transform origin — Defaults to element center, not top-left like CSS; use origin parameter for different behavior

Also see