documentationfor yFiles for HTML 2.6

Visualizing Arbitrary Objects

A GraphComponent can display visualizations for arbitrary objects, not just graph elements. In this section, we describe the steps required to insert a visualization for an arbitrary object into the view with a detailed explanation on what is happening for each step.

To visualize an arbitrary object, you need to add a new ICanvasObject to one of the ICanvasObjectGroup instances of your GraphComponent. ICanvasObjectGroup offers method addChild for this purpose:

const canvasObject = graphComponent.backgroundGroup.addChild(userObject, descriptor)

This poses the following questions for developers:

  • Which group to choose to add the canvas object to?
  • What is the user object that is passed to addChild?
  • What is the descriptor that is passed to addChild?
  • What is the returned ICanvasObject?

Choosing the Group to Add the Visualization to

There are several predefined groups in a GraphComponent that are described in The main canvas object groups. The most important ones are

  • the backgroundGroup for background visualizations (background images, maps),
  • the inputModeGroup for input-related decorations (e.g. handles, ghost visualizations), and
  • visualizations which should be in front of everything can be added to the rootGroup.

Instead of using one of the predefined ICanvasObjectGroups, you can create a new group (in one of the predefined groups) using method addGroup.

Providing a User Object and Choosing a Descriptor

User object and descriptor can be seen as a pair: the user object represents the object to render and the descriptor knows how to render the object. The descriptor implements ICanvasObjectDescriptor. Its methods receive the user object as a parameter and provide implementations that render the user object.

ICanvasObjectDescriptor provides descriptors for the most common use cases. It is almost never required to implement a custom ICanvasObjectDescriptor:

DYNAMIC_DIRTY_INSTANCE and ALWAYS_DIRTY_INSTANCE
the user object is an IVisualCreator that is responsible for creating the desired visualization.
// myVisualCreator is the custom IVisualCreator
const canvasObject = graphComponent.backgroundGroup.addChild(
  myVisualCreator,
  ICanvasObjectDescriptor.ALWAYS_DIRTY_INSTANCE
)

DYNAMIC_DIRTY_LOOKUP and ALWAYS_DIRTY_LOOKUP
the user object implements ILookup. Its lookup method has to provide an IVisualCreator implementation for creating the desired visualization. This is the case for graph items like nodes, for instance (although graph items typically use a specific descriptor that directly queries the style).
// the node provides an IVisualCreator via its lookup
const canvasObject = graphComponent.backgroundGroup.addChild(node, ICanvasObjectDescriptor.ALWAYS_DIRTY_LOOKUP)
VISUAL
the user object is already the Visual to display.
const image = window.document.createElementNS('http://www.w3.org/2000/svg', 'image')
image.setAttributeNS('http://www.w3.org/1999/xlink', 'href', 'resources/background.png')
image.x.baseVal.value = 1
image.y.baseVal.value = 1
image.width.baseVal.value = 100
image.height.baseVal.value = 100
const visual = new SvgVisual(image)
graphComponent.rootGroup.addChild(visual, ICanvasObjectDescriptor.VISUAL)

Using visuals directly is a quick and handy way of adding a custom visualization. Keep in mind, however, that it does not work well when the whole visualization is re-created for other purposes, e.g. image export. In that case you may either get exceptions or the visuals disappear from the control, since they can only exist in one place at the same time.

Keep the Reference to the Canvas Object

addChild returns an instance of type ICanvasObject. This type represents the entity that is drawn in the view and connects your object to its visualization.

You can use the ICanvasObject to manipulate the rendering of the object further. You can reorder the object in its layer, make it temporarily invisible (visible), remove it from the view entirely, change the previously set ICanvasObjectDescriptor, etc.

Example and Demo

The following sample shows how to add and remove a custom visualization of a rectangle in the background of a GraphComponent. The implementation of the IVisualCreator is shown in the example A custom IVisualCreator implementation.

// creates the canvas object on the background group
/**
 * @param {!GraphComponent} graphComponent
 */
install(graphComponent) {
  // use a custom visual creator as the user object
  const userObject = new RectangleVisualCreator(new Rect(-50, -50, 100, 100))

  // add it to the background
  this.canvasObject = graphComponent.backgroundGroup.addChild(
    userObject,
    ICanvasObjectDescriptor.ALWAYS_DIRTY_INSTANCE
  )
}

// removes the canvas object
uninstall() {
  if (this.canvasObject != null) {
    this.canvasObject.remove()
  }
}
// the created canvas object
canvasObject = null

// creates the canvas object on the background group
install(graphComponent: GraphComponent) {
  // use a custom visual creator as the user object
  const userObject = new RectangleVisualCreator(new Rect(-50, -50, 100, 100))

  // add it to the background
  this.canvasObject = graphComponent.backgroundGroup.addChild(
    userObject,
    ICanvasObjectDescriptor.ALWAYS_DIRTY_INSTANCE
  )
}

// removes the canvas object
uninstall() {
  if (this.canvasObject != null) {
    this.canvasObject.remove()
  }
}
// the created canvas object
canvasObject: ICanvasObject | null = null

A more complex implementation of an IVisualCreator that visualizes the layers of a Hierarchical Layout is part of the Interactive Hierarchic Layout demo.