Options
All
  • Public
  • Public/Protected
  • All
Menu

ts-svgmanager

TS-SVGManager

A Typescript SVG Manager library

Provides classes used to manage interactive SVG's in the HTML DOM, minimize definitions and make controlling the SVG elements from JS/TS as easy and reliable as possible.

Look at the Docs for detailed information

Installation

Install the package using npm:

npm install ts-svgmanager

Why use SVGManager

SVGManager creates a resourceful and compact way to handle interactive SVG containers. SVGManager provides a easy way to deal with events and mentions of nodes within a SVG container, so that you can come back and adjust them.

Getting started

Drawing a simple Circle

Here we are going to draw a simple circle to the DOM using the manager. There are a some predeclared shapes, which can we very easily drawn using the standard functions. Here we are gonna use the standard circle.

Code

HTML

In the HTML we define a container, which we can mention later within the typescript/javascript.

<body>
    <!-- ... Rest of DOM ... -->
    <div id="svg-root"></div>
    <!-- ... Rest of DOM ... -->
</body>

JS/TS

In the typescript/javascript files, we can then initiate a manager and render a circle within that.

import { SVGManager } from 'ts-svgmanager'
import { circle } from 'ts-svgmanager/Shapes'

// Initialize the SVGManager to the container
const manager = new SVGManager().init('svg-root')

// Render a circle with a radius of 25 at (50, 50)
manager.render(circle(25, 50, 50))

This will look like:

Drawing a Pentagon

Now we going to draw a bit more difficult of a shape a pentagon.

JS/TS

import { SVGManager } from 'ts-svgmanager'
import { polygon } from 'ts-svgmanager/Shapes'

// Again we initialize the SVGManager
const manager = new SVGManager().init('svg-root')

// Then we render a pentagon
manager.render(
    polygon([
        { x: 20, y: 10 },
        { x: 80, y: 10 },
        { x: 95, y: 60 },
        { x: 50, y: 95 },
        { x: 5, y: 60 },
    ]),
)

This will look like:

Adding a gradient

If we want to add a gradient a background we use the Gradient Helper. This will turn the code into this:

import { SVGManager } from 'ts-svgmanager'
import { polygon } from 'ts-svgmanager/Shapes'
import { SVGLinGradient, SVGStops } from 'ts-svgmanager/helpers'

// Again we initialize the SVGManager
const manager = new SVGManager().init('svg-root')

// Define a gradient into the manager using the Gradient Helper
const blueGradient = manager.define(
    new SVGLinGradient(
        new SVGStops()
            .stop(0, 'rgb(72, 60, 102)')
            .stop(1, 'rgb(136, 169, 197)'),
    )
        .spreadMethod('pad')
        .x1(0)
        .y1(0)
        .x2(0.87)
        .y2(1.11),
)

// Render a pentagon with a custom fill
manager.render(
    polygon([
        { x: 20, y: 10 },
        { x: 80, y: 10 },
        { x: 95, y: 60 },
        { x: 50, y: 95 },
        { x: 5, y: 60 },
    ]),
    .fillDef(blueGradient),
)

This will look like:

Adding animations

Now we are gonna add animations to a shape. The Animate Helper will help a lot with this. We are gonna use the ellipse shape here.

JS/TS

import { SVGManager } from 'ts-svgmanager'
import { SVGLinGradient, SVGStops, SVGAnimate } from 'ts-svgmanager/helpers'
import { ellipse } from 'ts-svgmanager/Shapes'

// Initialize the SVGManager
const manager = new SVGManager().init('svg-root')

// We add a gradient for some color
const orangeGradient = manager.define(
    new SVGLinGradient(
        new SVGStops()
            .stop(0, 'rgb(255, 156, 96)')
            .stop(1, 'rgb(245, 125, 125)'),
    )
        .spreadMethod('pad')
        .x1(0)
        .y1(0)
        .x2(1.28)
        .y2(0.47),
)

// Render a ellipse at (50,50) and add the gradient and the animations
manager.render(
    ellipse(20, 40, 50, 50)
        .fillDef(orangeGradient)
        .animate(new SVGAnimate(2000, 'rx', [20, 40, 20]).repeatIndefinitely())
        .animate(new SVGAnimate(2000, 'ry', [40, 20, 40]).repeatIndefinitely()),
)

This will look like:

Loading from files

Now we are going to show how you could load a svg element from a file. We are going to do this using the Parser Helper.

JS/TS

import { SVGManager, SVGNode } from 'ts-svgmanager'
import { fetchSVGNode } from 'ts-svgmanager/helpers'
import { rect } from 'ts-svgmanager/Shapes'

// Initialize the SVGManager
const manager = new SVGManager()
manager.init('svg-root')

// Fetch the SVG node from the file
fetchSVGNode('./gradient.svg').then((node: SVGNode) => {
    const blueGradient = manager.define(node)

    // Render a rect with the blue gradient
    manager.render(rect(10, 10, 80, 80).fillDef(blueGradient))
})

gradient.svg

<linearGradient
    spreadMethod="pad"
    id="gradient"
    x1="0%"
    y1="0%"
    x2="87%"
    y2="111%"
>
    <stop offset="0%" style="stop-color:rgb(72, 60, 102);stop-opacity:1;" />
    <stop offset="100%" style="stop-color:rgb(136, 169, 197);stop-opacity:1;" />
</linearGradient>

This will look like:

Adding events

Now we are going to add some events to this rectangle. We are going to create a mouseover event.

JS/TS

import { SVGManager } from 'ts-svgmanager'
import { SVGLinGradient, SVGStops } from 'ts-svgmanager/helpers'
import { rect } from 'ts-svgmanager/Shapes'

// Initialize the SVGManager
const manager = new SVGManager()
manager.init('svg-root')

const blueGradient = manager.define(
    new SVGLinGradient(
        new SVGStops()
            .stop(0, 'rgb(72, 60, 102)')
            .stop(1, 'rgb(136, 169, 197)'),
    )
        .spreadMethod('pad')
        .x1(0)
        .y1(0)
        .x2(0.87)
        .y2(1.11),
)
const orangeGradient = manager.define(
    new SVGLinGradient(
        new SVGStops()
            .stop(0, 'rgb(255, 156, 96)')
            .stop(1, 'rgb(245, 125, 125)'),
    )
        .spreadMethod('pad')
        .x1(0)
        .y1(0)
        .x2(1.28)
        .y2(0.47),
)

manager.render(
    rect(10, 10, 80, 80)
        .fillDef(blueGradient)
        .on('mouseenter', (_e, node) => node.fillDef(orangeGradient))
        .on('mouseleave', (_e, node) => node.fillDef(blueGradient)),
)

Declaring custom shapes

import { SVGManager, SVGNode } from 'ts-svgmanager'
import { PathData } from 'ts-svgmanager/helpers'

// Initialize a circle with args
const pill = new SVGNode('path')
    .set(
        'd',
        new PathData()
            .moveTo(10, 40)
            .lineTo(10, 60)
            .curveTo(30, 60, 10, 70, 30, 70)
            .lineTo(30, 40)
            .curveTo(10, 40, 30, 30, 10, 30)
            .closePath(),
    )
    .stroke('#000', '1px')
    .fill('none')

// Initialize the SVGManager
const manager = new SVGManager()
manager.init('svg-root')

// Render this
manager.render(pill)

This will look like:

Putting it together

We are gonna create a custom cursor for our SVG.

Here is how we do it:

import { SVGManager } from 'ts-svgmanager'
import ViewBox from 'ts-svgmanager/helpers/ViewBox'
import { circle } from 'ts-svgmanager/Shapes'

// Initializing the SVGManager with a viewBox of '-30 -30 60 60'
const manager = new SVGManager()
    .init('svg-root')
    .viewBox(new ViewBox(0, 0, 200, 200))
    .width(200)
    .height(200)
    .set('cursor', 'none')

// Rendering a circle with a radius of 5 at (0,0)
manager.render(circle(5).tag('custom-cursor').cx(-20).cy(-20))

// Adding the onmousemove listener
manager.on('mousemove', (ev: MouseEvent, svgNode) => {
    // Get the position of the SVG element
    const svgX = svgNode.element.getBoundingClientRect().x,
        svgY = svgNode.element.getBoundingClientRect().y

    // Get the x and y of the mouse relative to the SVG
    const x = ev.clientX - svgX,
        y = ev.clientY - svgY

    // Move the cursor to this location
    manager.tagged('custom-cursor').forEach((cursor) => cursor.cx(x).cy(y))
})

View on CodeSandbox

Thank you for reading! Go have fun!

Generated using TypeDoc