documentationfor yFiles for HTML 3.0.0.1

Visualizing Arbitrary Objects

A GraphComponent can display visualizations for arbitrary objects, not just graph elements. This section describes the steps to insert a visualization for an arbitrary object into the view, with a detailed explanation of each step.

To visualize an arbitrary object, you need to add a new IRenderTreeElement to one of the IRenderTreeGroup instances of your GraphComponent. The GraphComponent's renderTree offers the method createElement<TRenderTag> for this purpose:

const renderTree = graphComponent.renderTree
const renderTreeElement = renderTree.createElement(
  renderTree.backgroundGroup,
  renderTag,
  renderer
)

This raises the following questions for developers:

  • Which group should I choose to add the render tree element to?
  • What render tag should I pass to createElement<TRenderTag>?
  • What renderer should I pass to createElement<TRenderTag>?
  • What is the returned IRenderTreeElement?

Choosing the Group to Add the Visualization to

There are several predefined groups in a GraphComponent, which are described in The main render tree groups. The most important groups are:

  • The backgroundGroup for background visualizations, such as background images or maps.
  • The inputModeGroup for input-related decorations, such as handles or ghost visualizations.
  • The foregroundGroup, where visualizations are placed that should appear in front of everything else.

Instead of using one of the predefined IRenderTreeGroups, you can create a new group, possibly within one of the predefined groups, using the createGroup method.

Providing a Render Tag and Choosing a Renderer

A render tag and its renderer form a pair: the render tag identifies the object to render, and the renderer knows how to render that object. The renderer implements IObjectRenderer<TRenderTag>. Its methods receive the render tag as a parameter and provide the implementation to render the render tag.

The different createElement overloads cover the most common use cases:

createElement(IRenderTreeGroup, IVisualCreator)
the render tag is an IVisualCreator that is responsible for creating the desired visualization.
const renderTree = graphComponent.renderTree
// myVisualCreator is a custom IVisualCreator
const renderTreeElement = renderTree.createElement(
  renderTree.backgroundGroup,
  myVisualCreator
)

createElement(IRenderTreeGroup, Visual)
the render tag 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)
const renderTree = graphComponent.renderTree
renderTree.createElement(renderTree.rootGroup, visual)

Using visuals directly is a convenient way to add a custom visualization. However, this approach may not be suitable when the entire visualization is re-created for other purposes, such as image export. In such cases, you might encounter exceptions, or the visuals might disappear from the control, since they can only exist in one place at a time.
createElement(IRenderTreeGroup, ILookup)
the render tag implements ILookup. Its lookup method must 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 renderer that directly queries the style).
const renderTree = graphComponent.renderTree
// the node provides an IVisualCreator via its lookup
const renderTreeElement = renderTree.createElement(
  renderTree.backgroundGroup,
  node
)

Keep the Reference to the Render Tree Element

createElement<TRenderTag> returns an instance of type IRenderTreeElement. This type represents the entity that is drawn in the view and connects your object to its visualization.

You can use the IRenderTreeElement to further manipulate the rendering of the object. For example, you can: * Reorder the object in its layer. * Make it temporarily invisible (visible). * remove it from the view entirely. * Change the previously set IObjectRenderer<TRenderTag>.

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.

// the created render tree element
renderTreeElement = null

// creates the render tree element on the background group
install(graphComponent) {
  // use a custom visual creator as render tag
  const visualCreator = new RectangleVisualCreator(
    new Rect(-50, -50, 100, 100)
  )
  // add it to the background
  const renderTree = graphComponent.renderTree
  this.renderTreeElement = renderTree.createElement(
    renderTree.backgroundGroup,
    visualCreator
  )
}

// removes the render tree element
uninstall() {
  if (this.renderTreeElement != null) {
    this.graphComponent.renderTree.remove(this.renderTreeElement)
  }
}

// the created render tree element
renderTreeElement: IRenderTreeElement | null = null

// creates the render tree element on the background group
install(graphComponent: GraphComponent) {
  // use a custom visual creator as render tag
  const visualCreator = new RectangleVisualCreator(
    new Rect(-50, -50, 100, 100)
  )
  // add it to the background
  const renderTree = graphComponent.renderTree
  this.renderTreeElement = renderTree.createElement(
    renderTree.backgroundGroup,
    visualCreator
  )
}

// removes the render tree element
uninstall() {
  if (this.renderTreeElement != null) {
    this.graphComponent!.renderTree.remove(this.renderTreeElement)
  }
}

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