JavaScript
With build process​
The standard way to use JointJS is by importing the @joint/core
or @joint/plus
package as a dependency with a package manager of your choice. Follow the steps in our Quickstart installation guide to get started.
You can access JointJS features by importing them from the respective package, like this:
- JointJS
- JointJS+
import { dia, shapes } from '@joint/core';
Without build process​
JointJS can be used without any build process. It is as simple as including the UMD version of JointJS in your HTML with a <script>
tag, which enables you to use JointJS functionality on your website.
- JointJS
- JointJS+
Include the UMD distribution of JointJS into your HTML. Most commonly, this means loading it from a CDN such as jsDelivr or UNPKG:
- jsDelivr
- UNPKG
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://cdn.jsdelivr.net/npm/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://unpkg.com/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Alternatively, you may download the file manually and place it into the same folder as your HTML
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Loading the joint.js
file before your own code (index.js
in the above example), exposes three global variables with JointJS functionality:
joint
(most functionality)g
(Geometry)V
(Vectorizer)
Instead of relying on import
statements, you access JointJS objects via these global variables. For example:
const namespace = joint.shapes;
instead ofimport { shapes } from '@joint/core'; const namespace = shapes;
const graph = new joint.dia.Graph(/*...*/);
instead ofimport { dia } from '@joint/core'; const graph = new dia.Graph(/*...*/);
Let's illustrate this by modifying the final JointJS Quickstart demo accordingly. Note the use of joint.
everywhere:
// create paper
const namespace = joint.shapes;
const graph = new joint.dia.Graph({}, { cellNamespace: namespace });
const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
model: graph,
width: 300,
height: 300,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace
});
// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(25, 25);
rect1.resize(180, 50);
rect1.addTo(graph);
const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(95, 225);
rect2.resize(180, 50);
rect2.addTo(graph);
rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });
// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);
link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });
Frequently asked questions​
Can I use JointJS without a build process (as a UMD package)?​
Yes, but there are a few differences from the usual installation process.
Learn more...
Include the UMD distribution of JointJS into your HTML. Most commonly, this means loading it from a CDN such as jsDelivr or UNPKG:
- jsDelivr
- UNPKG
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://cdn.jsdelivr.net/npm/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="https://unpkg.com/@joint/core/dist/joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Alternatively, you may download the file manually and place it into the same folder as your HTML
<html>
<head>
<meta charset="utf8"/>
<title>JointJS UMD Installation example</title>
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint.js"></script>
<script src="index.js"></script>
</body>
</html>
Loading the joint.js
file before your own code (index.js
in the above example), exposes three global variables with JointJS functionality:
joint
(most functionality)g
(Geometry)V
(Vectorizer)
Instead of relying on import
statements, you access JointJS objects via these global variables. For example:
const namespace = joint.shapes;
instead ofimport { shapes } from '@joint/core'; const namespace = shapes;
const graph = new joint.dia.Graph(/*...*/);
instead ofimport { dia } from '@joint/core'; const graph = new dia.Graph(/*...*/);
Let's illustrate this by modifying the final JointJS Quickstart demo accordingly. Note the use of joint.
everywhere:
// create paper
const namespace = joint.shapes;
const graph = new joint.dia.Graph({}, { cellNamespace: namespace });
const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
model: graph,
width: 300,
height: 300,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace
});
// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(25, 25);
rect1.resize(180, 50);
rect1.addTo(graph);
const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(95, 225);
rect2.resize(180, 50);
rect2.addTo(graph);
rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });
// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);
link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });
Can I use JointJS+ without a build process (as a UMD package)?​
Yes, but there are a few differences from the usual installation process.
Learn more...
Place the UMD distribution of JointJS+, plus its CSS definition, into the same folder as your HTML:
- Navigate to the
build/package
folder inside the unzipped JointJS+ archive. - Copy the
joint-plus.js
file and paste it into the same folder as your HTML. - Copy the
joint-plus.css
file and paste it into the same folder as your HTML.
Include joint-plus.js
and joint-plus.css
in your HTML:
<html>
<head>
<meta charset="utf8"/>
<title>JointJS+ UMD Installation example</title>
<link rel="stylesheet" type="text/css" href="joint-plus.css" />
<!--<link rel="stylesheet" type="text/css" href="styles.css" />-->
</head>
<body>
<div id="paper"></div>
<script src="joint-plus.js"></script>
<script src="index.js"></script>
</body>
</html>
Loading the joint-plus.js
file before your own code (index.js
in the above example), exposes three global variables with JointJS functionality:
joint
(all JointJS+ functionality and most JointJS functionality)g
(Geometry)V
(Vectorizer)
Instead of relying on import
statements, you access JointJS objects via these global variables. For example:
const namespace = joint.shapes;
- instead of
import { shapes } from '@joint/plus'; const namespace = shapes;
- instead of
const graph = new joint.dia.Graph(/*...*/);
- instead of
import { dia } from '@joint/plus'; const graph = new dia.Graph(/*...*/);
- instead of
const paperScroller = new joint.ui.PaperScroller(/*...*/);
- instead of
import { ui } from '@joint/plus'; const paperScroller = new ui.PaperScroller(/*...*/);
- instead of
Let's illustrate this by modifying the final JointJS+ Quickstart demo accordingly. Note the use of joint.
everywhere:
// create paper scroller
const namespace = joint.shapes;
const graph = new joint.dia.Graph({}, { cellNamespace: namespace })
const paper = new joint.dia.Paper({
model: graph,
width: 2000,
height: 2000,
background: { color: '#F5F5F5' },
cellViewNamespace: namespace,
defaultRouter: { name: 'orthogonal' },
defaultConnector: { name: 'straight', args: { cornerType: 'line' }}
});
const paperScroller = new joint.ui.PaperScroller({
paper: paper,
scrollWhileDragging: true
});
document.getElementById('paper').appendChild(paperScroller.render().el);
// implement pinch interaction
paper.on('paper:pinch', (_evt, ox, oy, scale) => {
const zoom = paperScroller.zoom();
paperScroller.zoom(zoom * scale, { min: 0.2, max: 5, ox, oy, absolute: true });
});
// create elements
const rect1 = new joint.shapes.standard.Rectangle();
rect1.position(875, 885);
rect1.resize(180, 50);
rect1.addTo(graph);
const rect2 = new joint.shapes.standard.Rectangle();
rect2.position(945, 1065);
rect2.resize(180, 50);
rect2.addTo(graph);
rect1.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect2.attr('body', { stroke: '#C94A46', rx: 2, ry: 2 });
rect1.attr('label', { text: 'Hello', fill: '#353535' });
rect2.attr('label', { text: 'World!', fill: '#353535' });
// create link
const link = new joint.shapes.standard.Link();
link.source(rect1);
link.target(rect2);
link.addTo(graph);
link.appendLabel({
attrs: {
text: {
text: 'to the'
}
}
});
link.router('orthogonal');
link.connector('straight', { cornerType: 'line' });
// center content
paperScroller.centerContent();
// create stencil
const stencil = new joint.ui.Stencil({
paper: paper,
width: 170,
height: '100%',
layout: true,
dropAnimation: true
});
stencil.render();
document.getElementById('stencil').appendChild(stencil.el);
const elements = [
{
type: 'standard.Rectangle',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
rx: 2,
ry: 2
}
}
},
{
type: 'standard.Ellipse',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
}
}
},
{
type: 'standard.Polygon',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
points: 'calc(w/2),0 calc(w),calc(h/2) calc(w/2),calc(h) 0,calc(h/2)'
}
}
},
{
type: 'standard.Cylinder',
size: { width: 70, height: 50 },
attrs: {
body: {
stroke: '#C94A46',
},
top: {
fill: '#C94A46',
stroke: '#C94A46'
}
}
}
];
stencil.load(elements);
// create halo
function openHalo(cellView) {
new joint.ui.Halo({ cellView: cellView }).render();
}
paper.on('cell:pointerup', (cellView) => {
openHalo(cellView);
});
// open halo for first element by default
openHalo(paper.findViewByModel(rect1));
// create toolbar
const toolbar = new joint.ui.Toolbar({
tools: [
{
type: 'button',
name: 'json',
text: 'Export JSON'
},
{
type: 'button',
name: 'svg',
text: 'Export SVG'
},
'separator',
'zoomToFit',
'zoomSlider'
],
references: {
paperScroller: paperScroller
}
});
toolbar.render();
document.getElementById('toolbar').appendChild(toolbar.el);
toolbar.on('json:pointerclick', () => {
const str = JSON.stringify(graph.toJSON());
const bytes = new TextEncoder().encode(str);
const blob = new Blob([bytes], { type: 'application/json;charset=utf-8' });
joint.util.downloadBlob(blob, 'joint-plus.json');
});
toolbar.on('svg:pointerclick', () => {
joint.format.toSVG(
paper,
(svg) => {
joint.util.downloadDataUri(
`data:image/svg+xml,${encodeURIComponent(svg)}`,
'joint-plus.svg'
);
},
{ useComputedStyles: false }
);
});
// create inspector
function openInspector(cell) {
closeInspector(); // close inspector if currently open
joint.ui.Inspector.create('#inspector', {
cell: cell,
inputs: getInspectorConfig(cell)
});
}
function closeInspector() {
joint.ui.Inspector.close();
}
function getInspectorConfig(cell) {
if (cell.isElement()) {
return {
attrs: {
label: {
text: {
type: 'content-editable',
label: 'Label'
}
}
}
};
} else { // cell.isLink()
return {
labels: {
type: 'list',
label: 'Labels',
item: {
type: 'object',
properties: {
attrs: {
text: {
text: {
type: 'content-editable',
label: 'Text',
defaultValue: 'label'
}
},
},
position: {
type: 'select-box',
options: [
{ value: 30, content: 'Source' },
{ value: 0.5, content: 'Middle' },
{ value: -30, content: 'Target' }
],
defaultValue: 0.5,
label: 'Position'
}
}
}
}
};
}
}
paper.on('cell:pointerdown', function (cellView) {
openInspector(cellView.model);
});
stencil.on('element:drop', function (elementView) {
openInspector(elementView.model);
});
paper.on('blank:pointerdown', () => {
closeInspector(); // close inspector if currently open
});
// open inspector for first element by default
openInspector(rect1);