Skip to main content

Halo

JointJS+ provides a Halo plugin that enables the ability to create a control panel above an element with various tools.

Installation

Access Halo via the ui namespace, create an instance. Then, provide the view of the cell, and call the render() method.

import { dia, shapes, ui } from '@joint/plus';

const graph = new dia.Graph({}, { cellNamespace: shapes });
const paper = new dia.Paper({
el: document.getElementById('paper'),
width: 500,
height: 500,
model: graph,
cellViewNamespace: shapes
});

paper.on('element:pointerup', (elementView) => {
const halo = new ui.Halo({ cellView: elementView });
halo.render();
});
There is also a UMD version available

Include joint.ui.halo.js and joint.ui.halo.css in your HTML:

index.html
<link rel="stylesheet" type="text/css" href="joint.ui.halo.css">
<script src="joint.js"></script>
<script src="joint.ui.halo.js"></script>

Access Halo through the joint.ui namespace:

index.js
const graph = new joint.dia.Graph({}, { cellNamespace: joint.shapes });
const paper = new joint.dia.Paper({
el: document.getElementById('paper'),
width: 500,
height: 500,
model: graph,
cellViewNamespace: joint.shapes
});

paper.on('element:pointerup', (elementView) => {
const halo = new joint.ui.Halo({ cellView: elementView });
halo.render();
});

How does Halo work?

Halo provides the user with the ability to create a control panel above an element that contains various useful tools. This gives the user control over their elements via an easily accessible set of actions. The ui.Halo requires the view of a cell we want to display the halo above.

In the following example, a halo is shown immediately on a rectangle element, and upon user interaction with the elements, a halo is also added.

Disabling halo tools

The built-in halo tools are remove, resize, rotate, clone, fork, link, and unlink. You can call the removeHandle() method to remove any of these tools just by passing its name:

halo.removeHandle('clone');

Alternatively, you can disable tools via CSS:

.halo .handle.clone { display: none; } /* disables the clone tool */

Additionally, in the same manner you would hide halo tools, as explained above, you can reposition them. For example, to reposition the remove icon tool to the bottom left corner, you could do:

.halo .handle.remove {
left: -25px;
bottom: -25px;
top: auto;
right: auto;
}

Note that the auto values for the top/right coordinates are important in order to cancel out the default values defined in the Halo plugin.

Another way to remove/reposition tool handles for the halo is in JavaScript:

halo.removeHandle('clone');
halo.changeHandle('remove', { position: 'se' });

The code above removes the clone tool from the halo, and re-positions the remove tool to the bottom right (south-east).

Each halo can also be styled in CSS (disabling tools, repositioning, changing icons, ...) based on the type of element the halo is displayed for. The halo <div> container stores the type of the element in its data-type attribute. This makes it easy to target a halo for a certain type of element in your CSS. For instance, let's say we want to hide the remove tool only for an element of type "standard.Rectangle". You can do this:

.halo[data-type="standard.Rectangle"] .remove { display: none; }

Customizing halo tools

Halo provides three methods for adding, removing and changing custom tools: addHandle(), removeHandle() and changeHandle(). Use the addHandle() method to add new tools to your halo:

halo.addHandle({ name: 'myaction', position: 's', icon: 'myaction.png' });

halo.on('action:myaction:pointerdown', (evt) => {
evt.stopPropagation();
alert('My custom action.');
});

In the example above, we added a new tool named myaction, positioned the tool to the south (bottom-center), and used our own icon myaction.png. When the user clicks on our tool, Halo triggers an event named action:[name]:pointerdown. We can handle the event by listening on the halo object. Similarly, the Halo triggers action:[name]:pointermove, and action:[name]:pointerup events. This gives us a high flexibility in implementing our own actions.

For removing a halo tool, use the removeHandle(name) method:

halo.removeHandle('myaction');

The changeHandle() method allows us to change halo tool handles. For instance, if we want to change the position of the clone tool, we could use:

halo.changeHandle('clone', { position: 'se' });

Pie menu type of Halo

To display the Halo control panel as a pie menu, just set the type option to 'pie':

new ui.Halo({ cellView: myElementView, type: 'pie' });

You can still add your own actions as you would normally do with the default 'surrounding' type of Halo.

Toolbar type of Halo

To display the Halo control panel as a small toolbar above an element, just set the type option to 'toolbar':

new joint.ui.Halo({ cellView: myElementView, type: 'toolbar' });

You can still add your own actions as you would normally do with the default 'surrounding' type of Halo.

It is also possible to use the Halo plugin with links, as the following demo illustrates.