Skip to main content

Magnetizer

The magnetizer is a core piece of Toolkit UI functionality, which inter-operates with layouts to provide a means to nudge elements around in your UI so that things don't overlap. There are a few different ways to use the magnetizer.

Auto magnetization

All layouts support the option of switching on magnetization, which is run after the layout runs. For some layouts this ability is theoretically of no use, for instance the [layout-force-directed](Force directed layout), as in that layout the elements in your UI have already been moved apart by the layout itself. But if you're using, for instance, the [layout-absolute](Absolute layout), then there is a chance one or more elements are overlapping.

You can switch on magnetization in a layout by setting it as a layout option:

{
layout:{
type:"Absolute",
options:{
magnetize:true
}
}
}

Each time the layout runs, the magnetizer will be run afterwards.

It is possible for a layout to declare that it wishes permanent magnetization to be switched on by default. The Spring layout does this, for example. But note that Spring layout is now deprecated, in favour of the Force directed layout.

Adhoc magnetization

You can instruct the Surface widget to run the magnetizer over the entire contents of the UI at any time via the magnetize method:

magnetize(focus?:string|Vertex):void

By default, the magnetizer will use the computed center of all the elements as its origin, and all elements will be pushed away from that point, as in this call:

surface.magnetize()

An alternative, though, is to supply a vertex that you wish to act as the origin, and which you do not wish to move:

surface.magnetize("nodeId")

Here we passed the ID of some node, but we could also have passed the node itself. The signature of the magnetize method is:

magnetize(focus?:string|Vertex):void

Setting a vertex position and magnetizing

Another feature the Surface offers is the ability to set the position of some element and to immediately magnetize the UI after setting the element's position, using that element as the focus:

setMagnetizedPosition(element:string|Vertex, x:number, y:number):void

This is effectively the same as:

surface.setPosition(element, x, y)
surface.magnetize(element)

This operation is wrapped in a transaction on the Toolkit so if undo is called then every element affected by the magnetize is relocated to its original position.

Magnetizer options

Aside from the setMagnetizedPosition method, the Surface offers a few different options for configuring the magnetizer automatically:

Home > @jsplumbtoolkit/browser-ui > SurfaceMagnetizeOptions

SurfaceMagnetizeOptions interface

Options for the magnetize functionality of the Surface.

Signature:

export interface SurfaceMagnetizeOptions 

Properties

PropertyModifiersTypeDescription
afterDrag?boolean(Optional) If true, magnetizer will be run after a vertex is dragged.
afterGroupCollapse?boolean(Optional) Defaults to false. Indicates the surface should gather nodes around a newly collapsed group
afterGroupExpand?boolean(Optional) Defaults to false. Indicates the surface should magnetize nodes around a newly expanded group
afterGroupGrow?boolean(Optional) Defaults to false. Indicates the surface should magnetize/gather nodes around a newly resized group if the group size was enlarged.
afterGroupResize?boolean(Optional) Defaults to false. Indicates the surface should magnetize/gather nodes around a newly resized group, regardless of whether the group size grew or if it shrunk. This flag is the same as setting afterGroupShrink and afterGroupGrow
afterGroupShrink?boolean(Optional) Defaults to false. Indicates the surface should magnetize/gather nodes around a newly resized group if the group size was reduced.
afterLayout?boolean(Optional) If true, magnetizer will be run after the layout is run.
constant?boolean(Optional) If true, magnetizer will be run constantly as a vertex is being dragged, pushing other vertices out of the way of the vertex that is being dragged
constrainToViewport?boolean(Optional) If true, vertices moved by the magnetizer will be constrained to move within the visible viewport, which is a function of the current zoom/pan of the surface. Otherwise, vertices will be able to be pushed out of the visible viewport.
repositionDraggedElement?boolean(Optional) If true, and afterDrag is true, when the magnetizer is run after a drag it will be the recently dragged element that moves in precedence to the other elements. By default, the recently dragged element is _not_ moved by the magnetize operation - it stays where you dragged it.

These options should be supplied as the render options for a Surface, either in a render call when using vanilla Toolkit:

myToolkit.render(someElement, {

magnetize:{

...

}
})

or as the render options you pass in to a Surface component when using Angular, React, Vue or Svelte.

Gathering Elements

The magnetizer can also gather elements to bring them closer together around some origin. Internally this works by pulling each affected element in on its radial from the origin to the element's center, and then running the magnetizer to nudge everything back out so that nothing overlaps.

gather(focus?:string|Vertex):void

To gather all the elements in the UI around their computed center, don't supply a focus element:

surface.gather()

To gather all the elements in the UI around some focus element:

surface.gather(idOrVertex)