documentationfor yFiles for HTML 2.6

WebGL2 Rendering

Sometimes it is necessary to visualize large graphs entirely to get an overview of the data. Then, the focus lies on the connections and clusters of elements rather than the details of single nodes and edges.

Therefore, yFiles for HTML offers a rendering mechanism that uses WebGL2 to provide hardware-accelerated graph rendering and interaction. WebGL2 is integrated into modern browsers and allows for calculating all graphics operations directly on the GPU (graphics processing unit). Hence, the rendering works parallel to the CPU operations which makes applications faster and more responsive.

Selecting graph elements on click is supported by fast WebGL2 hit-testing to provide the usual interactions like moving or deleting elements, adding bends, resizing nodes, or editing labels.

Although all layout algorithms of yFiles for HTML work in combination with the WebGL2 rendering, some handle large graphs better than others. Use HierarchicLayout, OrganicLayout, TreeLayout, and BalloonLayout depending on what layout style is needed.

Modern browsers like Chrome, Edge, Opera, Firefox and Safari (on macOS 12 and iOS 15) support WebGL2 rendering out of the box. In Safari on older macOS and iOS versions, it is available as an experimental feature and needs to be enabled in the developer menu Experimental Features.

yFiles for HTML supports both WebGL and WebGL2 rendering. However, it should be noted that these technologies are implemented differently and therefore cannot be used in combination. It is highly recommended to utilize WebGL2 rendering unless compatibility issues or other reasons demand the use of WebGL.

The decision between using WebGL2 rendering or SVG rendering depends on various factors including the specific use-case and the size of the graph being displayed. Consider the details of your project and the performance requirements before choosing a rendering method.

Comparison of Render Modes
WebGL2 Rendering SVG Rendering
Fast rendering of more than 20000 elementsPixel-perfect visualization of nodes and edges
A limited number of styles for nodes, edges, and labelsFlexible and highly customizable visualizations of nodes, edges, and labels
Predefined and easy-to-apply animations like blinking or pulsing of graph elementsCustomizable animations added in CSS and JavaScript

From the comparison above, it follows that SVG rendering is the better choice for detailed representations or applications that require precise user interaction. WebGL rendering is more suitable for larger graphs (from 1000 nodes upwards, often only for substantially larger graphs), when performance is more important than detailed representations.

Compared to SVG rendering, the most prominent limitations of WebGL2 rendering include:

  • only the predefined styles are available, custom styles cannot be defined
  • some interactions appear to be rough. For example, when a node is resized the positions of its labels and decorations are only updated at the end of the gesture
  • snapping is not supported
  • changing the z-order of the graph elements is partially supported

Enabling WebGL Rendering

Using WebGL2 rendering in an application requires setting the WebGL2GraphModelManager on the GraphComponent. It will provide support for rendering graphs with WebGL2.

For interactive applications which support selection, moving, resizing and deleting graph elements, WebGL2SelectionIndicatorManager provides a high-performance selection rendering that integrates with WebGL2 rendering.

Enabling WebGL2 rendering
graphComponent.graphModelManager = new WebGL2GraphModelManager()
graphComponent.selectionIndicatorManager = new WebGL2SelectionIndicatorManager()

The WebGL2 Rendering tutorial demonstrates how to enable the WebGL2 rendering for a graph.

WebGL2 Styles

The WebGL2 rendering comes with a predefined set of styles for nodes, edges, and labels. WebGL2GraphModelManager infers the WebGL2 styles from the styles set on the graph. Since the WebGL2 styles can only render a subset of the regular styles, this matching may not be exact. Hence, it is possible to assign custom styles to graph elements directly on the WebGL2GraphModelManager.

Node Styles

There are some predefined shapes for the visualization of nodes. Also, the colors for the background and border are customizable. It is easy to attach an effect like a drop shadow or an ambient shine around the node.

Specifying a style for a node
// set the node style directly on the graph
graph.setStyle(node, new ShapeNodeStyle({ shape: 'ellipse', fill: 'green', stroke: '1px black' }))

// set the WebGL2 shape node style on the WebGL2GraphModelManager
webGL2GraphModelManager.setStyle(
  node,
  new WebGL2ShapeNodeStyle({
    shape: 'ellipse',
    fill: 'green',
    stroke: 'black'
  })
)

Optionally, nodes can display a centered icon. This icon must be pre-rendered and must be set directly on the WebGL2GraphModelManager. It cannot be inferred from the ImageNodeStyle. The number of displayable icons depends on the graphic card’s memory size.

Using a node style with icon
// canvas used to pre-render the icons
const canvas = document.createElement('canvas')
canvas.setAttribute('width', '128')
canvas.setAttribute('height', '128')
const ctx = canvas.getContext('2d')

const image = new Image(imageWidth, imageHeight)
image.onload = () => {
  // render the image into the canvas
  ctx.drawImage(image, 0, 0, imageWidth, imageHeight, 0, 0, 128, 128)
  const imageData = ctx.getImageData(0, 0, 128, 128)
  const nodeStyle = new WebGL2IconNodeStyle({
    icon: imageData
  })
  const node = graph.createNodeAt(location)
  // assign the webgl2 node style
  webGL2GraphModelManager.setStyle(node, nodeStyle)
}
image.src = url// canvas used to pre-render the icons
const canvas = document.createElement('canvas')
canvas.setAttribute('width', '128')
canvas.setAttribute('height', '128')
const ctx = canvas.getContext('2d')!

const image = new Image(imageWidth, imageHeight)
image.onload = () => {
  // render the image into the canvas
  ctx.drawImage(image, 0, 0, imageWidth, imageHeight, 0, 0, 128, 128)
  const imageData = ctx.getImageData(0, 0, 128, 128)
  const nodeStyle = new WebGL2IconNodeStyle({
    icon: imageData
  })
  const node = graph.createNodeAt(location)
  // assign the webgl2 node style
  webGL2GraphModelManager.setStyle(node, nodeStyle)
}
image.src = url

The WebGL2 Icon Node demo presents nodes with different font awesome icons.

Edge Styles

There are three ways to visualize edges: as a polyline, an arc or a bridge. Edges can have different arrows on the source, target, or both sides. The color of the line is customizable.

Edges whose source and target node are the same are either displayed as circles or as rectangles.

Specifying styles for edges
// set the polyline edge style directly on the graph
graph.setStyle(
  polylineEdge,
  new PolylineEdgeStyle({
    stroke: '2px green',
    targetArrow: 'triangle'
  })
)

// set the WebGL polyline edge style on the WebGL2GraphModelManager
webGL2GraphModelManager.setStyle(
  polylineEdge,
  new WebGL2PolylineEdgeStyle({
    stroke: '2px green',
    targetArrow: 'triangle'
  })
)

// set the arc edge style directly on the graph
graph.setStyle(
  arcEdge,
  new ArcEdgeStyle({
    height: 10,
    stroke: '2px green',
    targetArrow: 'triangle'
  })
)

// set the WebGL arc edge style on the WebGL2GraphModelManager
webGL2GraphModelManager.setStyle(
  arcEdge,
  new WebGL2ArcEdgeStyle({
    height: 10,
    stroke: '2px green',
    targetArrow: 'triangle'
  })
)

Label Styles

Both nodes and edges can have labels. Those labels can have custom colors for text and background, different fonts, and custom insets. It is recommended to set a DefaultLabelStyle on the graph and let the WebGL2GraphModelManager infer the WebGL2DefaultLabelStyle for the labels automatically. That ensures that they have the correct size.

Specifying a style for a label
// set the label style directly on the graph
graph.setStyle(
  label,
  new DefaultLabelStyle({
    textFill: 'black',
    backgroundFill: '#FFFFFFBB',
    font: '16px sans-serif',
    textSize: 16
  })
)

// when setting the WebGL node style on the WebGL2GraphModelManager, make sure to also set a
// DefaultLabelStyle with the same settings to get the label's size correctly
webGL2GraphModelManager.setStyle(
  label,
  new WebGL2DefaultLabelStyle({
    textColor: 'black',
    backgroundColor: '#FFFFFFBB',
    font: '16px sans-serif'
  })
)

As usual, the label layout parameter specifies the position of the labels. The WebGL2 rendering supports all locations for edge and node labels. However, the interactive behavior for edge labels always resembles the one of the FreeLabelModel. The memory of the graphic card and the sizes of the label texts determine the number of labels that can be rendered.

Directing Attention with Animations

The WebGL2 API comes with several predefined animations that can be applied to nodes, edges, and labels. Such animations can help to direct the attention to single elements or parts of graph. There are animations that affect the size of a node or label, or the thickness of an edge like pulsating, while other animations will change the location of a graph element to produce a vibration effect. Another group of animations will change the color of a graph element or let it fade in or out.

WebGL2GraphModelManager provides factory methods to create those animations. They can be specified for nodes, edges, and labels.

Specifying animations
// create a fade-out animation
const fadeAnimation = webGL2GraphModelManager.createFadeAnimation(WebGL2FadeAnimationType.FADE_OUT)
// create a pulse animation that pulsates twice by the amount of 5
const pulseAnimation = webGL2GraphModelManager.createPulseAnimation(WebGL2PulseAnimationType.GROW, 10, false, '1s 10')
// create a shake animation that shakes ten times by the amount of 2
const shakeAnimation = webGL2GraphModelManager.createShakeAnimation({
  type: 'horizontal',
  magnitude: 2,
  // CSS-like shorthand for timing - auto-converted to WebGL2AnimationTiming
  // 500ms duration, eased, 20 iterations, alternating animation
  timing: '500ms ease 20 alternate'
})

// apply animation to a node
webGL2GraphModelManager.setAnimations(node, [fadeAnimation])

// apply animation to an edge
webGL2GraphModelManager.setAnimations(edge, [pulseAnimation])

// apply animation to a label
webGL2GraphModelManager.setAnimations(label, [shakeAnimation])

// apply multiple animations to a node
webGL2GraphModelManager.setAnimations(node, [fadeAnimation, shakeAnimation, pulseAnimation])

// clear all animations for a node
webGL2GraphModelManager.setAnimations(node, [])

The animations are specified in an array because it is possible to have several animations assigned to an element.

Animations should be shared and unassigned when not in use as the maximum number of assigned animations is limited to 15 per type of element. There can be only 8 animations assigned to one element at the same time, and only 31 different combinations of animations may be assigned to the items.To clear all animations for a given element, provide an empty animation array.

Level of Detail Rendering

To have fast hardware-accelerated rendering for the view of the complete graph and detailed pixel-perfect rendering for a closer view of the graph elements, you can switch between the two rendering modes depending on the zoom level.

For a smooth and unnoticeable transition, choose styles like ShapeNodeStyle and ImageNodeStyle for both the detailed and the general view of the nodes. They have matching WebGL2 node styles. Alternatively, the detailed view can show a different and more detailed view of a node that highlights its attached information.

The Large Graphs demo showcases the level of detail switch from WebGL2 to SVG rendering and vice versa.

WebGL2 Support

All modern browsers like Chrome, Edge, Opera, Firefox, and Safari (on macOS 12 and iOS 15) support WebGL2 out of the box, and yFiles has been tested with recent versions of Chrome, Edge, Firefox, and Safari. In Safari on older macOS and iOS versions, it is available as an experimental feature and needs to be enabled in the developer menu Experimental Features.

However, due to the hardware acceleration, it is more dependent related to the client’s system than the browser native rendering techniques like SVG or canvas rendering. We found that WebGL2 rendering usually works best on desktop systems and most mobile devices, although the mobile devices are more susceptible to rendering artifacts.

WebGL2 Troubleshooting

This section explains how to deal with WebGL2 rendering issues and low frame rates.

Dealing with Rendering Issues

When some labels or icons are invisible, yFiles runs out of GPU texture memory. To fix this issue, reduce the number of different labels or icons, reduce the label size (e.g., smaller font size, shorter text), or reduce the icon size. If this does not suffice, a graphics card with more texture memory is required.

Other rendering issues like invisible elements, artifacts, flickering, or wrong background colors usually originate from outdated software. yFiles has been tested with recent versions of Chrome, Edge, Firefox, and Safari. When encountering rendering issues, make sure to use the latest versions of operating system, graphics card driver, and browser. Note that WebGL2 support in Safari is only enabled out of the box on iOS 15 and newer. On older iOS versions, it is marked as experimental and needs to be enabled manually.

Dealing with Low Frame Rate

The reasons for a low frame rate are manifold. One of them is that the browser does not use the GPU for rendering and instead uses software-emulation to run WebGL2 code on the CPU. Make sure that hardware acceleration is enabled in the browser’s settings and that your combination of hardware, operating system, and browser supports hardware acceleration.

Another reason for bad performance is a weak graphics card. Note, though, that usually even current CPU-integrated GPUs are capable of smoothly rendering large graphs of 50,000 elements and more. In order to render way more than 50,000 nodes and edges, a dedicated graphics card might be required. If you have multiple graphics cards, make sure the browser uses the most powerful one.

ImageNodeStyle and IconLabelStyle are not auto-converted

The method getWebGL2NodeStyle cannot automatically convert instances of ImageNodeStyle to WebGL2IconNodeStyle since its image cannot be converted in synchronous code. Similarly, the method getWebGL2LabelStyle cannot automatically convert instances of IconLabelStyle to WebGL2IconLabelStyle.