Skip to main content

Release 6.8.0

· 3 min read
Simon Porritt

NEW FUNCTIONALITY

  • Shape libraries now support defs - snippets of SVG that you can declare in the header of a shape set and reference in the individual templates. This reduces bloat and increases readability. See below for more detail.

UPDATES

  • Improvements to the hierarchy layout's crossing stage to reduce the chance of overlapping edges
  • Improvements to SVG/PNG/JPG export UI
  • Improvements to SVG export output: edges are drawn first in the SVG so that nodes will be placed on top in non-browser settings.

Shape Library Defs

In most UIs there is some amount of markup that is common amongst a number of vertices. For instance, in the network topology diagram below, there are three types of nodes - terminal, cloud and switch, each of which has its own icon representing it:

In version 6.8.0 we have added support for a defs element to shape sets - it is a wrapper for the defs element in SVG. The benefits of using defs are that you can reduce the number of elements in your DOM, and when exporting the SVG the resulting file will be smaller and easier to comprehend.

To configure this, we created a shape set like this:

const shapes = {
id: "networkTopology",
name: "NetworkTopology",
defs:{
"jtk-switch":`<svg:svg viewBox="0 0 1024 1024">
<svg:path d="..."/>
</svg:svg>`,
"jtk-cloud":`<svg:svg viewBox="0 0 100 100">
<svg:path d="..."/>
</svg:svg>`,
"jtk-terminal":`<svg:svg viewBox="0 0 32 32">
<svg:path d="..." />
</svg:svg>`
},
shapes: {
"cloud": {
type: "cloud",
template: `<svg:use xlink:href="#jtk-cloud" x="0" y="0" width="60" height="60"/>`
},
"switch": {
type: "switch",
template: `<svg:use xlink:href="#jtk-switch" x="0" y="0" width="60" height="60"/>`
},
"terminal": {
type: "terminal",
template: `
<svg:g>
<svg:use xlink:href="#jtk-terminal" x="0" y="0" width="60" height="60"/>
<svg:text x="30" y="25" text-anchor="middle" dominant-baseline="middle" stroke-width="0.25px">{{label}}</svg:text>
</svg:g>
`
}
}
}

I've truncated the actual SVG elements for readability's sake, but these are the things to note:

  • Each def has an svg element at its root, with a viewBox. This is not essential, but in this case our icons came from various different places and had different base sizes. The viewBox allows us to map them to the size we want.
  • Each def has a single root element. This is mandatory. Use an svg:g element as the root if you want to group a few elements.
  • The markup for each def is parsed by the Toolkit's default template engine and therefore must include namespaces and be XHTML, ie. no unclosed tags.
  • The IDs of the various defs must be unique in the window, so choose carefully. We typically prefix with a namespace (jtk- here).

We then render a surface using this shape library:

import { newInstance, ShapeLibraryImpl, DEFAULT } from "@jsplumbtoolkit/browser-ui"

const shapes = {...}
const sl = new ShapeLibraryImpl([shapes])
const tk = newInstance()

tk.render(container, {
...
shapes:{
library:sl
},
view:{
nodes:{
[DEFAULT]:{
template:`
<div data-jtk-target="true" style="width:60px;height:60px;">
<jtk-shape width="60" height="60"/>
</div>`
}
}
}
})

Further reading

You can read up on this in our documentation - https://docs.jsplumbtoolkit.com/toolkit/6.x/lib/shape-sets.


Start a free trial

Sending your evaluation request...

Interested in the concepts discussed in this article? Start a free trial and see how jsPlumb can help bring your ideas to market in record time.


Get in touch!

If you'd like to discuss any of the ideas/concepts in this article we'd love to hear from you - drop us a line at hello@jsplumbtoolkit.com.