Skip to main content

SVG Shapes

Diagrams use SVG to render shapes. These shapes are stored inside ShapeSets, and when you create a diagram you instruct VisuallyJs which shape sets you want to use.

Registering shapes​

import { FLOWCHART_SHAPES, BASIC_SHAPES } from "@visuallyjs/browser-ui"
import { VisuallyJsModule } from "@visuallyjs/browser-ui-angular";
import {Component} from "@angular/core";

@Component({
template:`<div style="width:100%;height:500px">
<vjs-diagram [data]="data" [options]="options"/>
</div>`
export class MyComponent {
data = ...

options = {
shapes: [FLOWCHART_SHAPES, BASIC_SHAPES]
}
}

Required data properties​

In order for the diagram to be able to pick the appropriate shape for some vertex, the vertex data must contain:

  1. A type property that maps to the ID of one of the shapes in your library
  2. A category property that maps to some shape set ID
  3. A width and height value for each node. The SVG shapes use path elements internally, which require absolute coordinates, and so they need to know the current size of your vertices.
  4. An x and y value for each node

Optional data properties​

The full list of optional data properties depends on the shape libraries you are using, but all of the VisuallyJs libraries support these optional properties:

  • fill - Color to fill the shape with. Defaults to #FFFFFF.
  • outline - Color to outline the shape with. Defaults to #000000.
  • outlineWidth - Width of the shape's outline. Defaults to 2px.
  • color - Color to use for the shape's label (if shown). Defaults to #000000.

As an example, consider this list of two nodes:

[
{
"id":"1",
"x":50,
"y":50,
"type":"process",
"category":"flowchart",
"width":100,
"height":100,
"fill":"white",
"outline":"black"
},
{
"id":"2",
"x":150,
"y":250,
"type":"terminus",
"category":"flowchart",
"width":100,
"height":100,
"fill":"white",
"outline":"black"
}
]

This is rendered as:

Displaying Labels​

By default, a diagram will display a label value from each node - if we add label to the vertices from before we'll see them:

[
{
"id":"1",
...,
"label":"Node 1"
},
{
"id":"2",
...,
"label":"Node 2"
}
]

Hiding labels​

You can hide labels by setting showLabels:false in your diagram's edges options:

import { FLOWCHART_SHAPES, BASIC_SHAPES } from "@visuallyjs/browser-ui"
import { VisuallyJsModule } from "@visuallyjs/browser-ui-angular";
import {Component} from "@angular/core";

@Component({
template:`<div style="width:100%;height:500px">
<vjs-diagram [data]="data" [options]="options"/>
</div>`
export class MyComponent {
data = ...

options = {
shapes: [FLOWCHART_SHAPES, BASIC_SHAPES],
edges: {
showLabels: false
}
}
}

Available sets​

VisuallyJs ships with two shape sets in the browser-ui package and a set of BPMN shapes:

Flowchart​

import { FLOWCHART_SHAPES } from "@visuallyjs/browser-ui"
processdecisionterminusinputdocumentmanualInputmanualOperationpreparationconnectormergecollatesubroutineorloopLimitdelaydisplaydatabasedataStorage

Basic​

import { BASIC_SHAPES } from "@visuallyjs/browser-ui"
rectanglerounded-rectangleellipsediamondisosceles-triangleinverted-isosceles-triangleright-trianglelabelinverted-right-trianglehexagonhexagon-flatoctagonpentagonparallelogramtrapezoidcrossl-shape-bll-shape-brl-shape-tll-shape-tru-shapeinverted-u-shape

BPMN​

import { BPMN2_SHAPES } from "@visuallyjs/bpmn"
start-eventend-eventintermediate-eventgatewaytasktransactioncall-activitysubprocessgroupdataObjectdataStoreReferencepoollane
info

These shapes are shipped in the @visuallyjs/bpmn library - you'll need to import it.


Custom shape sets​

It's straightforward to make your own shape set - they consist of an id and then a list of shapes, for each of which you provide SVG.

Here we have made a set of faces:

const shapes = {
id:"faces",
shapes:[
{
type:"impassive",
template:`<g>
<circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2)}}"/>
<path d="M {{width/4}} {{height*3/4}} L {{width*3/4}} {{height*3/4}}"/>
<circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
</g>`,
label:"Impassive"
},
{
type:"pleased",
template:`<g>
<circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2)}}"/>
<circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
<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}}"/>
</g>`,
label:"Pleased"
},
{
type:"notpleased",
template:`<g>
<circle cx="{{width/2}}" cy="{{height/2}}" r="{{(width/2)}}"/>
<circle cx="{{width/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width*3/4}}" cy="{{height/4}}" r="10"/>
<circle cx="{{width/2}}" cy="{{height/2}}" r="10"/>
<path d="M {{width/4}} {{height*3/4}} C {{width/4}} {{height*5/8}}, {{width*3/4}} {{height*5/8}} {{width * 0.75}} {{height * 0.75}}"/>
</g>`,
label:"Not Pleased"
}
]
}

Nested Shape sets​

It is possible to nest shape sets, via the children property of a shape set. For instance, say we want to split our set of faces into two subsets:

const shapes = {
id:"faces",
children:[
{
id:"expressionless",
name:"Expressionless",
shapes:[
{
id:"impassive",
template:`...`
}
]
},
{
id:"expressions",
name:"Expressions",
shapes:[
{
id:"pleased",
template:`...`
},
{
id:"notpleased",
template:`...`
}
]
}
]
}