documentationfor yFiles for HTML 2.6

Changing the Z-order

For most use cases you work with the GraphModelManager and its convenience methods to adjust the z-order of elements in the view to your needs.

The WebGL2 rendering mode and the associated WebGL2GraphModelManager support only some of the features described in this section.

In the following sections, we’ll discuss the benefits of the default z-order, introduce the general API to re-order objects, and describe how to change the z-order of graph elements and of the visualizations of selection, focus, and custom highlight. Finally, we describe how you can implement your own GraphModelManager for full control of the rendering order.

General Thoughts

In our experience, one of the most common reasons to change the default z-order is the rendering of node labels that are placed inside of the bounds of their owner nodes. If two nodes overlap, both labels are fully visible on top of both nodes since by default all labels are drawn in front of all nodes. This makes it hard to decide which label belongs to which node and in general just looks strange to many people. For this usecase it is sufficient to change the LabelLayerPolicy.

Effect of LabelLayerPolicy
SEPARATE_LAYER
AT_OWNER

Similar confusion can arise for example for overlapping nodes and their ports, which can be solved by changing the PortLayerPolicy, and for edges that cross through unrelated nodes and groups.

For all these cases, we recommend considering ways to avoid the overlaps instead of spending time for customizing the z-order. The benefit will be a more readable diagram.

The default z-order realized by GraphModelManager works very well for almost all cases except for the ones mentioned above. In particular,

  • Rendering labels in the front ensures that their full text is readable even if there are some unavoidable overlaps. This is typically the desired behavior for all edge labels and for node labels that are not placed inside their owner.
  • If groups are present, edges are interleaved with the rendering of the groups to make sure that their first and last segments are not covered by the groups of their source and target nodes. Since in addition the rendering of nested groups and nodes must be consistent, some edges might be forced to cross in the front (or back) of an unrelated group in an undesired way.

The Default Z-order of Edges and Groups

Clearly, the children of a group should be rendered in front of the group instead of behind it. For edges, it’s more complicated. By default, edges are drawn behind nodes. However, when a node outside of a group has an edge to a node that is part of a group or if the group node itself has an edge to a child of his, then the edge is hidden in a way that makes it unclear where the edge connects to or if there is an edge at all.

Because of this, yFiles for HTML by default interleaves the rendering order of nodes and edge in such a way that hierarchical structures are considered. Edges that connect to nodes inside a group are drawn on a higher level than edges that connect nodes on the same level as the group node.

You can choose another preconfigured nesting policy by changing the property hierarchicNestingPolicy.

The Z-order of Graph Elements

The z-order of all visualized items is managed by an internal visual tree that consists of hierarchic nested ICanvasObjectGroup that have ICanvasObject implementations as leaf nodes. Each item that shall be visualized is represented by an ICanvasObject or ICanvasObjectGroup and the order of ICanvasObject in their ICanvasObjectGroup corresponds to the z-order or the represented items.

What ICanvasObjectGroup are used and in which ICanvasObjectGroup an ICanvasObject is placed is determined by the the chosen HierarchicNestingPolicy, PortLayerPolicy and LabelLayerPolicy.

With WebGL2 rendering, there is only one ICanvasObject that represents the complete WebGL2 rendering, and the described policy properties have no effect. You can however change the z-order of graph item types by reordering the sub-groups listed below.

The content group is a high-level group that contains a sub-group for each kind of graph element. Due to the chosen aforementioned policies, some of the groups might be unused.

From front to back, these groups are:

  1. portLabelGroup. It contains the visualization for the labels of ports.
  2. nodeLabelGroup. It contains the visualization for the labels of nodes.
  3. edgeLabelGroup. It contains the visualization for the labels of edges.
  4. portGroup. It contains the visualization for the ports.
  5. nodeGroup. By default it contains the visualizations for the nodes and edges.
  6. edgeGroup. It is unused by default and contains the visualizations for the edges if hierarchicNestingPolicy is not set to NODES_AND_EDGES.
  7. groupNodeGroup. It is unused by default and contains the visualizations for group nodes if hierarchicNestingPolicy is set to GROUP_NODES.

The following table describes which groups are used for nodes and edges depending on the hierarchicNestingPolicy:

Effect of HierarchicNestingPolicy on the ICanvasObjectGroup of nodes and edges
Policy Group Nodes Leaf Nodes Edges
NONEnodeGroupnodeGroupedgeGroup
NODESchild group of parent node in nodeGroupchild group of parent node in nodeGroupedgeGroup
NODES_AND_EDGESchild group of parent nodechild group of parent nodechild group of the common ancestor of the edge’s source and target node in nodeGroup
GROUP_NODESchild group of groupNodeGroup according to the nesting depthnodeGroupedgeGroup

The groups for ports and labels depends on the chosen PortLayerPolicy and LabelLayerPolicy:

Effect of PortLayerPolicy on the ICanvasObjectGroup of ports
Policy Labels
AT_OWNERchild group of port owner
SEPARATE_LAYERportGroup
Effect of LabelLayerPolicy on the ICanvasObjectGroup of labels
Policy Labels
AT_OWNERchild group of label owner
SEPARATE_LAYERnodeLabelGroup, edgeLabelGroup or portLabelGroup depending on the kind of label owner

Re-ordering Model Items

GraphModelManager provides methods that re-order IModelItem in their layer which changes the order in which the elements of this layer are rendered. Re-ordering Model Items presents the methods and what they do.

With WebGL2 rendering, the rendering order of individual elements cannot be changed in this way.

Convenience Methods that change the order of model items in their layer.
toFront(item: IModelItem): void
Moves the element to the end of the rendering list, causing it to be drawn last and therefore to be rendered in the front.
toFront(items: IEnumerable<IModelItem>): void
Moves the elements to the end of the rendering list, causing them to be drawn last and therefore to be rendered in the front. The relative order of the elements is preserved.
toBack(item: IModelItem): void
Moves the element to the start of the rendering list, causing it to be drawn first and therefore to be rendered in the back. The relative order of the elements is preserved.
toBack(items: IEnumerable<IModelItem>): void
Moves the elements to the start of the rendering list, causing them to be drawn first and therefore to be rendered in the back. The relative order of the elements is preserved.
raise(item: IModelItem): void
Changes the place of this element with its successor in the list, causing it to be rendered in front of its former successor.
raise(items: IEnumerable<IModelItem>): void
Changes the place of the elements with their successor in the list, causing them to be rendered in front of their former successor. The relative order of the elements is preserved.
lower(item: IModelItem): void
Changes the place of this element with its predecessor in the list, causing it to be rendered behind its former predecessor.
lower(items: IEnumerable<IModelItem>): void
Changes the place of the elements with their predecessor in the list, causing them to be rendered behind their former predecessor. The relative order of the elements is preserved.

Let us illustrate changing the order with a simple example. We create three overlapping nodes: first n1, then n2, and finally n3. The rendering order is n1, n2, n3, and therefore, n1 is the undermost and n2 the topmost node.

Now we raise n2, so the rendering order is now n1, n3, n2, and n2 is topmost.

Raising n2
graphComponent.graphModelManager.getMainCanvasObject(n2).raise()

If we want n1 to be the topmost node, we simply move it to the end of the rendering order.

Bringing n1 to the front
graphComponent.graphModelManager.getMainCanvasObject(n1).toFront()
Changing the rendering order of nodes
Rendering order after node creation.
Raised n2 up …​
…​ and brought n1 to front.

For interactive scenarios a common usecase is to change the z-order for all selected model items. GraphEditorInputMode provides the following methods for exactly this purpose:

selectionToFront(): void
Moves the selected elements to the end of the rendering list keeping their relative order and causing them to be drawn last and therefore to be rendered in the front.
selectionToBack(): void
Moves the selected elements to the start of the rendering list keeping their relative order and causing them to be drawn first and therefore to be rendered in the back.
raiseSelection(): void
Changes the place of the selected elements with their successor in the list keeping their relative order and causing them to be rendered in front of their former successor.
lowerSelection(): void
Changes the place of the selected elements with their predecessor in the list keeping their relative order and causing them to be rendered behind their former predecessor.

All these convenience methods change the order of the ICanvasObjects of the model items which can be retrieved using GraphModelManager's method getMainCanvasObject.

ICanvasObject offers two more methods that are especially handy to change the z-order of the graph element groups:

above(reference: ICanvasObject): ICanvasObject
Re-inserts this element after the given element in the rendering list, causing it to be rendered right above the given element.
below(reference: ICanvasObject): ICanvasObject
Re-inserts this element before the given element in the rendering list, causing it to be rendered right below the given element.

By default yFiles for HTML draws edges that cross group nodes behind the group nodes. A common use case is to change this behavior so that edges are drawn in front of group nodes.

Changing the rendering order of edges and group nodes
Default rendering order
Changed rendering order

To achieve this you just have to configure the GraphModelManager as shown in the following code snippet.

Drawing edges in front of group nodes
const graphModelManager = graphComponent.graphModelManager
// draw all edges in a single layer
graphModelManager.hierarchicNestingPolicy = HierarchicNestingPolicy.GROUP_NODES
// move the edge layer in front of the node layer
graphModelManager.edgeGroup.above(graphModelManager.nodeGroup)

Z-order Commands

The raise, lower, toFront and toBack methods described in Re-ordering Model Items can also be triggered by the following commands:

Z-order commands with their accepted parameter and effects
Command Accepted Parameter Effect
ICommand.RAISEIModelItemCalls raise(IModelItem)
IEnumerable<T>Calls raise(IEnumerable<IModelItem>)
nullIf selection is not empty, raiseSelection() is called. Otherwise if GraphEditorInputMode.useCurrentItemForCommands is enabled, calls raise for the currentItem.
ICommand.LOWERIModelItemCalls lower(IModelItem)
IEnumerable<T>Calls lower(IEnumerable<IModelItem>)
nullIf selection is not empty, lowerSelection() is called. Otherwise if GraphEditorInputMode.useCurrentItemForCommands is enabled, calls lower(IModelItem) for the currentItem.
ICommand.TO_FRONTIModelItemCalls toFront(IModelItem)
IEnumerable<T>Calls toFront(IEnumerable<IModelItem>)
nullIf selection is not empty, selectionToFront() is called. Otherwise if GraphEditorInputMode.useCurrentItemForCommands is enabled, calls toFront(IModelItem) for the currentItem.
ICommand.TO_BACKIModelItemCalls toBack(IModelItem)
IEnumerable<T>Calls toBack(IEnumerable<IModelItem>)
nullIf selection is not empty, selectionToBack() is called. Otherwise if GraphEditorInputMode.useCurrentItemForCommands is enabled, calls toBack(IModelItem) for the currentItem.

The Z-order of Indicators

There is a dedicated canvas object group for each of the three kinds of indication. The main canvas object groups lists these and the other predefined groups.

Re-order these groups to change the order in which the different kinds of decorations are drawn. To change the drawing order of decorations of the same kind, re-order them in the corresponding group.

Completely Customize the Z-order

All of the above mentioned approaches together offer a good set of possibilities to control the z-order of elements. However, you gain full control of the z-order by subclassing GraphModelManager and overriding a few methods. This way, you can implement your own Z-order for the elements.

One set of methods that can be overridden are the factory methods for the ICanvasObjectGroups. There is one factory method for each sub-group of the content group of the GraphComponent. Additionally, the factory method for the content group itself can be overridden on GraphComponent.

Another possibility is to implement your own set of ICanvasObjectGroups and override the methods that specify in which group an item should be placed. For example, getNodeCanvasObjectGroup can be overridden to distribute nodes to different groups by certain characteristics. There are also methods for the other items as well.