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.
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:
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.
You can instruct the Surface widget to run the magnetizer over the entire contents of the UI at any time via the
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:
An alternative, though, is to supply a vertex that you wish to act as the origin, and which you do not wish to move:
Here we passed the ID of some node, but we could also have passed the node itself. The signature of the
magnetize method is:
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)
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.
Aside from the
setMagnetizedPosition method, the Surface offers a few different options for configuring the magnetizer automatically:
Options for the magnetize functionality of the Surface.
export interface SurfaceMagnetizeOptions
|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?||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 |
These options should be supplied as the render options for a Surface, either in a
render call when using vanilla Toolkit:
or as the render options you pass in to a Surface component when using Angular, React, Vue or Svelte.
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.
To gather all the elements in the UI around their computed center, don't supply a focus element:
To gather all the elements in the UI around some focus element: