Shape Libraries
One of the Toolkit's most popular demonstration applications has always been the Flowchart Builder. In version 6.2.0 of the Toolkit we upgraded this demonstration application to support pluggable shape sets, which make use of the new browser-ui-shape-library
module.
This functionality is only available from version 6.2.0 of the Toolkit. Prior versions of the Toolkit do not offer this functionality.
Overview
A shape library is a set of named shapes that you will use to render SVG inside the vertices in your application. The type
of each vertex is used by the Toolkit to look up an appropriate shape to render.
Setup
You'll first need to create a ShapeLibraryImpl
and pass in a set of shapes to render:
import { FLOWCHART_SHAPES, ShapeLibraryImpl } from "@jsplumbtoolkit/browser-ui"
const shapeLibrary = new ShapeLibraryImpl(FLOWCHART_SHAPES)
You can use this shape library to do a couple of things:
- render SVG elements into your nodes
- create a
ShapeLibraryPalette
from which users can drag new SVG shapes onto your canvas. - export the Surface to an SVG, PNG or JPG (requires version 6.6.0 or later)
Shape sets
A shape library is a wrapper around one or more shape sets. Here we use FLOWCHART_SHAPES
- this is a set of shapes that ship with the Toolkit. You can read about the available shapes (and how to create your own set) on this page.
Rendering SVG into nodes
Note: this section discusses how to use a shape library to render SVG when you're using the Toolkit's vanilla templating mechanism. If you're using a library integration (Angular, React etc) you should check the docs for the library integration to find out how to perform the equivalent of what is discussed in this section.
Requirements
There are two things you need to configure - your node data, and a tag to render the SVG.
Node data
Your node data must contain:
- A
type
field that maps to the ID of one of the shapes in your library - A
width
andheight
value for each node. The SVG shapes usepath
elements internally, which require absolute coordinates, and so they need to know the current size of your vertices:
{
"id": "1",
"name": "Some Node",
"type": "process",
"width": 200,
"height": 200
}
[
{
"id":"1",
"left":50,
"top":50,
"type":"process",
"width":100,
"height":100,
"fill":"white",
"outline":"black",
"name": "Node 1"
},
{
"id":"2",
"left":150,
"top":250,
"type":"terminus",
"width":100,
"height":100,
"fill":"white",
"outline":"black",
"name": "Node 2"
}
]
Notice how each of the nodes has a type
, width
and height
property in its data. Also note the fill
and outline
values - these are optional, and can be used to control the, er, fill and outline. If you do not provide values for these you'll get the default SVG behaviour, which is, in most browsers, to use a fill
of "black". You can use CSS to apply a style to every node at once if individual fill and outline is not something you need to control:
.jtk-node svg {
fill:white;
stroke:black;
}
Registering the shape library
To get the Surface to render the individual SVG shapes you need to provide a shapes
object in your render params, with a reference to the library you have created. The render params used to generate the output above are:
const shapeLibrary = new ShapeLibraryImpl(FLOWCHART_SHAPES)
const renderParams = {
shapes:{
library:shapeLibrary
},
layout:{
type:AbsoluteLayout.type
},
defaults:{
anchor: AnchorLocations.AutoDefault,
endpoint: BlankEndpoint.type,
connector: OrthogonalConnector.type
},
zoomToFit:true,
view:{
nodes:{
default:{
template:`<div>
<jtk-shape/>
</div>`
}
},
edges:{
default:{
overlays:[
{
type:ArrowOverlay.type,
options:{
location:1
}
}
]
}
}
},
consumeRightClick:false
}
Note the jtk-shape
element in the template? The Surface added this custom tag as a result of us providing the shape library to its render parameters.
Displaying labels
You can request that the shape library render a label in the center of each of your nodes:
shapes:{
library:shapeLibrary,
showLabels:true,
labelAttribute:"name"
}
By default, the shape library will look for a data property label
in your node data. Here we have overridden that and told it to get the label from the node's name
property.
SVG shape tag
An alternative way to register the tag is manually, with a name you choose. This is only recommended if, for some reason, you don't want to use jtk-shape
in your templates, or if you have more than one shape library. To do this you replace the shapes
entry with tags
:
const renderParams = {
tags:{
"jtk-shape":shapeLibrary.getShapeTagDefinition()
},
layout:{
type:AbsoluteLayout.type
},
etc
Shape library palettes
A common requirement in apps that use a library of shapes is the ability to drag new shapes onto the canvas. The Toolkit offers drag/drop of new nodes via its SurfaceDropManager and DropManager classes, but in 6.2.0 we've also added a class that wraps the SurfaceDropManager
with a shape library - the ShapeLibraryPalette
.
To create a ShapeLibraryPalette
you first need to have created a shape library, as shown above. Then:
const palette = new ShapeLibraryPalette({
container:someDOMElement,
surface:someSurface,
shapeLibrary:aShapeLibrary
})
Adding this to the code we had above, we get this result. Elements can be dragged from the palette onto the canvas. Note that when you drag an element from the palette it is automatically scaled to match the zoom of the canvas at that time:
The full list of options for the ShapeLibraryPalette
class are as follows:
Home > @jsplumbtoolkit/browser-ui > ShapeLibraryPaletteOptions
ShapeLibraryPaletteOptions interface
Options for a shape library palette.
Signature:
export interface ShapeLibraryPaletteOptions<T extends ObjectData>
Properties
Property | Modifiers | Type | Description |
---|---|---|---|
canvasStrokeWidth? | number | (Optional) Stroke width to use for shapes dropped on canvas. Defaults to 2. | |
container | HTMLElement | The element to draw the palette into. | |
dataGenerator? | DataGeneratorFunction<T> | (Optional) Optional data generator to allow you to specify initial data for some element to be dragged. Note that you cannot override the object's type with this function. The palette will set the new object's type to match the type of the element that the user is dragging from the palette. | |
dragSize? | Size | (Optional) Optional size to use for dragged elements. | |
fill? | string | (Optional) Optional fill color to use for dragged elements. This should be in RGB format, _not_ a color like 'white' or 'cyan' etc. | |
iconSize? | Size | (Optional) Optional size to use for icons. Defaults to 150x100 pixels. If you provide this but not dragSize this size will also be used for an icon that is being dragged. | |
outline? | string | (Optional) Optional color to use for outline of dragged elements. Should be in RGB format. | |
paletteStrokeWidth? | number | (Optional) Stroke width to use for shapes in palette. Defaults to 1. | |
selectAfterDrop? | boolean | (Optional) When true (which is the default), a newly dropped vertex will be set as the underlying Toolkit's selection. | |
shapeLibrary | ShapeLibrary<T> | The shape library to render. | |
showAllMessage? | string | (Optional) Message to use for the 'show all' option in the shape set drop down when there is more than one set of shapes. Defaults to Show all . | |
surface | Surface | Surface to attach the drag/drop to. |
Export to SVG, PNG and JPG
As of version 6.6.0 you can export a UI that uses a shape library to SVG, PNG or JPG. See this page for more details.