Shape Sets
A ShapeSet
is a set of named shapes that a ShapeLibrary
can use to render SVG into vertex elements or a palette. The Toolkit currently ships with one set of shapes - FLOWCHART_SHAPES
, but it is a straightforward process to make your own set.
Structure
This is the basic structure - here we show the header and a few shapes from the flowchart shapes that ship with the Toolkit:
export const FLOWCHART_SHAPES = {
id:"flowchart",
name:"Flowchart",
shapes:{
"process": {
type: "process",
label: "Process",
template: '<svg:rect x="{{sw}}" y="{{sw}}" width="{{width-(sw*2)}}" height="{{height-(sw*2)}}"/>'
},
"decision": {
type: 'decision',
label: "Decision",
template: '<svg:path d="M {{width/2}} {{sw}} L {{width-sw}} {{height/2}} L {{width/2}} {{height-sw}} L {{sw}} {{height/2}} Z"/>'
},
"collate": {
type: "collate",
template: `<svg:g><svg:path d="M {{sw/2}} {{sw/2}} L {{width-sw}} {{sw/2}} L {{width/2}} {{height/2}} Z"/>
<svg:path d="M {{sw/2}} {{height-(sw/2)}} L {{width-sw}} {{height-(sw/2)}} L {{width/2}} {{height/2}} Z"/>
</svg:g>`
}
}
}
Each shape must have at least a type
and a template
value; label
is optional, and description
is also supported.
Template format
The template
must be in the format supported by the Toolkit's default templating engine, ie. XHTML, with every tag properly closed, and using a namespace prefix for SVG elements. Additionally, the template must have a single root element. Notice how in the collate
template we use a group element as the root, and put the other SVG elements inside of that.
Variable interpolation
When a shape library renders a shape, it presents three variables to the template engine:
width
When rendering a vertex this value will have been sourced from the vertex's backing data. When rendering a shape in a palette the palette sets a fixed value for this.height
When rendering a vertex this value will have been sourced from the vertex's backing data. When rendering a shape in a palette the palette sets a fixed value for this.sw
This is the stroke width to use in the resulting SVG. The various components of the shape library module default to a stroke width of 2 pixels, but you can override this. We include the stroke width in the template calculations in order to prevent clipping - theoretically it is possible to control stroke width via CSS but this does not always provide the best results. You do not need to include asw
value in your vertex backing data.
The template
you provide is inserted as a child element of an SVG element, whose viewBox
is set to 0 0 width height
. With this arrangement, your SVG will scale seamlessly if the size of a node changes.
Available sets
The Toolkit currently ships with one shape set - FLOWCHART_SHAPES
:
import { FLOWCHART_SHAPES, ShapeLibraryImpl } from "@jsplumbtoolkit/browser-ui"
const myLibrary = new ShapeLibraryImpl(FLOWCHART_SHAPES)
These are the flowchart shapes:
Custom shape sets
It's straightforward to make your own shape set. Here we have made a set of faces:
const shapes = {
id:"faces",
shapes:{
impassive:{
type:"impassive",
template:`<svg:g>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2) - (2*sw)}}"/>
<svg:path d="M {{width/4}} {{height*3/4}} L {{width*3/4}} {{height*3/4}}"/>
<svg:circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
</svg:g>`
},
pleased:{
type:"pleased",
template:`<svg:g>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2) - (2*sw)}}"/>
<svg:circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
<svg:path d="M {{width/4}} {{height*3/4}} C {{width/4}} {{height*7/8}}, {{width*3/4}} {{height*7/8}} {{width*3/4}} {{height*3/4}}"/>
</svg:g>`
},
notpleased:{
type:"notpleased",
template:`<svg:g>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2) - (2*sw)}}"/>
<svg:circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<svg:circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
<svg:path d="M {{width/4}} {{height*3/4}} C {{width/4}} {{height*5/8}}, {{width*3/4}} {{height*5/8}} {{width*3/4}} {{height*3/4}}"/>
</svg:g>`
}
}
}