Node style properties

May 6, 2024 ยท View on GitHub

Styling nodes and edges in Orb refers to the configuration of colors, size, width, and other visual properties. In the following section, you can find all the details and available style properties to set up for nodes and edges.

Node style properties

Once graph structure is created with orb.data.setup or update with orb.data.merge, a node (INode) object will be created upon your input data. Node object contains a property style through which you can get and set style properties.

const node = orb.data.getNodeById(0);
// Set node size to 10
node.style.size = 10;

Properties

The interface that defines all the node style properties is INodeStyle. It contains the following properties:

Property nameTypeDescription
borderColorColor | stringNode border color.
borderColorHoverColor | stringNode border color on mouse hover event. If not defined, borderColor is used.
borderColorSelectedColor | stringNode border color on mouse click event. If not defined, borderColor is used.
borderWidthnumberNode border width.
borderWidthSelectednumberNode border width on mouse click event. If not defined, borderWidth is used.
colorColor | stringNode background color. The default is #1d87c9.
colorHoverColor | stringNode background color on mouse hover event. If not defined color is used.
colorSelectedColor | stringNode background color on mouse click event. If not defined color is used.
fontBackgroundColorColor | stringNode text (label) background color.
fontColorColor | stringNode text (label) font color. The default is #000000.
fontFamilystringNode text (label) font family. The default is "Roboto, sans-serif".
fontSizenumberNode text (label) font size. The default is 4.
imageUrlstringImage used for a node background. If image is defined, color won't be used.
imageUrlSelectedstringImage used for a node background on mouse click event. If image is defined, colorSelected and color won't be used.
labelstringNode text content. Text content will be shown below the node if fontSize is greater than zero.
shadowColorColor | stringNode background shadow color.
shadowSizenumberNode shadow blur size. If set to 0 the shadow will be a solid color defined by shadowColor.
shadowOffsetXnumberNode shadow horizontal offset. A positive value puts the shadow on the right side of the element, a negative value puts the shadow on the left side of the element.
shadowOffsetYnumberNode shadow vertical offset. A positive value puts the shadow below the element, a negative value puts the shadow above the element.
shapeNodeShapeTypeNode shape enum. Possible values are: CIRCLE, DOT (same as circle), SQUARE, DIAMOND, TRIANGLE, TRIANGLE_DOWN, STAR, HEXAGON. Default is NodeShapeEnum.CIRCLE.
sizenumberNode size (usually the radius). The default is 5.
massnumberNode mass. (Currently not used)
zIndexnumberSpecifies the stack order of an element during rendering. The default is 0.

Shape enumeration

The enum NodeShapeType which is used for the node shape property is defined as:

export enum NodeShapeType {
  CIRCLE = 'circle',
  DOT = 'dot',
  SQUARE = 'square',
  DIAMOND = 'diamond',
  TRIANGLE = 'triangle',
  TRIANGLE_DOWN = 'triangleDown',
  STAR = 'star',
  HEXAGON = 'hexagon',
}

Default style values

Default node style values are defined as follows:

const DEFAULT_NODE_STYLE: INodeStyle = {
  size: 5,
  color: new Color('#1d87c9'),
  fontSize: 4,
  fontColor: '#000000',
  fontFamily: 'Roboto, sans-serif',
  shape: NodeShapeType.CIRCLE,
};

Note: By default, the Orb doesn't know which field to use as node text (label), so make sure to set node property label to the appropriate text that you want to show for each node. Check the example below:

const nodes: MyNode[] = [
  { id: 1, name: "First" },
  { id: 1, name: "Second" },
];

const orb = new Orb<MyNode, MyEdge>(container);
orb.data.setDefaultStyle({
  getNodeStyle: (node) => {
    return {
      ...node.style,
      label: node.data.name,
    };
  },
});
orb.data.setup({ nodes });

Edge style properties

Once graph structure is created with orb.data.setup or update with orb.data.merge, an edge (IEdge) object will be created upon your input data. Edge object contains a property style through which you can get and set style properties.

const edge = orb.data.getEdgebyId(0);
// Set edge width to 1
edge.style.width = 1;

Properties

The interface that defines all the node properties is IEdgeStyle. It contains the following style properties:

Property nameTypeDescription
arrowSizenumberThe scale of the edge arrow compared to the width of the edge. If set to 0, an arrow will be dismissed. The default is 1 (follows the size of the edge width).
colorColor | stringEdge line color. The default is #ababab.
colorHoverColor | stringEdge line color on mouse hover event. If not defined color is used.
colorSelectedColor | stringEdge line color on mouse click event. If not defined color is used.
fontBackgroundColorColor | stringEdge text (label) background color.
fontColorColor | stringEdge text (label) font color. The default is #000000.
fontFamilystringEdge text (label) font family. The default is "Roboto, sans-serif".
fontSizenumberEdge text (label) font size. The default is 4.
labelstringEdge text content. Text content will be shown at the middle of the edge line if fontSize is greater than zero.
shadowColorColor | stringEdge line background shadow color.
shadowSizenumberEdge line shadow blur size. If set to 0 the shadow will be a solid color defined by shadowColor.
shadowOffsetXnumberEdge shadow horizontal offset. A positive value puts the shadow on the right side of the line, a negative value puts the shadow on the left side of the line.
shadowOffsetYnumberEdge shadow vertical offset. A positive value puts the shadow below the line, a negative value puts the shadow above the line.
widthnumberEdge line width. If the width is 0, the edge won't be drawn. The default is 0.3.
widthHovernumberEdge line width on mouse hover event. If not defined width is used.
widthSelectednumberEdge line width on mouse click event. If not defined width is used.
zIndexnumberSpecifies the stack order of an element during rendering. The default is 0.

Default style values

Default edge style values are defined as follows:

const DEFAULT_EDGE_STYLE: IEdgeStyle = {
  color: new Color('#ababab'),
  width: 0.3,
  fontSize: 4,
  arrowSize: 1,
  fontColor: '#000000',
  fontFamily: 'Roboto, sans-serif',
};

Utility class Color

As you might have seen, all color-based style properties accept Color or string. A string value should always be a Color HEX code (e.g. #FFFFFF for white).

Orb exports a utility class Color which you can use to define colors too. It comes with several utility functions for easier color handling:

import { Color } from '@memgraph/orb';

// Constructor always receives a color HEX code
const red = new Color('#FF0000');

// Returns darker or lighter color by input factor (default is 0.3)
const darkerRed = red.getDarkerColor();
const lighterRed = red.getLighterColor();

// Mix two colors (RGB values are joined and divided by 2)
const mixedColor = red.getMixedColor(new Color('#ffffff'));

// Get a color object by RGB values, not HEX code
const redByRGB = Color.getColorFromRGB({ r: 255, g: 0, b: 0 });

// Get random color - great solution for all of you having issues finding a right color
const randomColor = Color.getRandomColor();

If you would like to have a lighter/darker tone of a node on node select/hover, then you can easily do that with getLighterColor or getDarkerColor functions:

const nodeBaseColor = new Color('#FF0000');

node.style.color = nodeBaseColor;
node.style.colorSelected = nodeBaseColor.getDarkerColor();
node.style.colorHover = nodeBaseColor.getLighterColor();

Setting up styles

There are two ways to set up a style:

  • Setting up default style which is an initial style applied to new nodes and new edges
  • Changing the style properties of particular nodes and edges

Setting default style

Orb comes with a default style which you can override with the function orb.data.setDefaultStyle. The function expects an object where you can define one or both style callback functions:

  • getNodeStyle(node) - expects an object containing node style properties.
  • getEdgeStyle(edge) - expects an object containing edge style properties.

The default style is an easy way to set up a style that will be applied to all newly created nodes or edges. With it, you don't need to worry about setting up style properties for each node or edge.

orb.data.setDefaultStyle({
  getNodeStyle(node) {
    return {
      color: '#FF0000',
      fontSize: 10,
      size: 10,
      label: `Node: ${node.data.title}`,
    };
  },
  getEdgeStyle() {
    return {
      color: '#000000',
      width: 3,
    };
  },
});
// From now on, every new node or edge created with `orb.data.setup` or
// `orb.data.merge` will get the initial style properties from the above
// style callback functions

// For all the `newNodes` and `newEdges` that have a new unique ID, a default
// style defined above will be automatically applied
orb.data.merge({ nodes: newNodes, edges: newEdges });

Without a default style, you would need to do the following after each call of orb.data.setup or orb.data.merge where new nodes/edges are created:

// Without default style, after each call of `orb.data.setup` or `orb.data.merge`
// you need to call the following code
orb.data.getNodes().forEach((node) => {
  node.style = {
    color: '#FF0000',
    fontSize: 10,
    size: 10,
    label: `Node: ${node.data.title}`,
  };
});
orb.data.getEdges().forEach((edge) => {
  edge.style = {
    color: '#000000',
    width: 3,
  };
});

// For all the `newNodes` and `newEdges` that have a new unique ID, Orb's default
// style will be applied, not the style properties above 
orb.data.merge({ nodes: newNodes, edges: newEdges });

Changing specific style properties

After calling orb.data.setup or orb.data.merge your node/edge data will be wrapped into a node (INode) or edge (IEdge) object. Using those objects, you can change their style properties any time:

import { OrbEventType } from '@memgraph/orb';

const orb = new Orb<MyNode, MyEdge>(container);
orb.data.setup({ nodes, edges });

const node = orb.data.getNodeById(0);
// Override existing node style properties with the new ones
node.style = {
  color: '#FF0000',
  fontSize: 10,
  size: 10,
  label: `Node: ${node.data.title}`,
};

// Change the width of all the edges to 1, but keep other style properties
orb.data.getEdges().forEach((edge) => {
  edge.style.width = 1;
});

orb.events.on(OrbEventType.NODE_CLICK, ({ node }) => {
  // If a node is clicked, set its size to be 10
  node.style.size = 10;
});

Configuring style globals

Each Orb view has render settings that you can configure which will affect global styling options. Usually, these settings are performance related, and you will get an idea of how to use them in the following section:

Disable/enable labels

Having labels (text) on nodes and edges will degrade the performance of the rendering for the large number of nodes/edges. To simplify the way to disable/enable labels for the whole graph without setting (node|edge).style.label = "" or (node|edge).style.fontSize = 0 for each node/edge, you can use the view settings to enable/disable labels globally:

// Change on view init
orb.setView((context) => new DefaultView(context, {
  render: {
    labelsIsEnabled: true,
    labelsOnEventIsEnabled: true,
  },
}));

// Change anytime for the current view
orb.view.setSettings({
  render: {
    labelsIsEnabled: true,
    labelsOnEventIsEnabled: true,
  },
});

Property labelsIsEnabled will affect all the nodes/edges while labelsOnEventIsEnabled will affect labels when node/edge is selected (clicked on) or hovered. Default values for both properties are true.

Disable/enable shadows

Just like labels, having shadows on nodes and edges will degrade the performance of the rendering for the large number of nodes/edges. To simplify the way to disable/enable shadows for the whole graph you can use the view settings to enable/disable shadows globally:

// Change on view init
orb.setView((context) => new DefaultView(context, {
  render: {
    shadowIsEnabled: true,
    shadowOnEventIsEnabled: true,
  },
}));

// Change anytime for the current view
orb.view.setSettings({
  render: {
    shadowIsEnabled: true,
    shadowOnEventIsEnabled: true,
  },
});

Property shadowsIsEnabled will affect all the nodes/edges while shadowsOnEventIsEnabled will affect shadows when node/edge is selected (clicked on) or hovered. Default values for both properties are true.

Configure transparency on hover/click

Additional performance affected property is the transparency of nodes/edges that are not selected nor hovered. Default Orb behavior on node/edge select (click) and hover to make all other nodes 30% transparent, so the selection/hover is easily visible.

You can configure the transparency with the following two properties:

  • contextAlphaOnEvent - Transparency factor between 0 (hidden) and 1 (opaque). The default is 0.3.
  • contextAlphaOnEventIsEnabled - Enable or disable transparency regardless of the factor. The default is true.
// Change on view init
orb.setView((context) => new DefaultView(context, {
  render: {
    contextAlphaOnEvent: 0.3,
    contextAlphaOnEventIsEnabled: true,
  },
}));

// Change anytime for the current view
orb.view.setSettings({
  render: {
    contextAlphaOnEvent: 0.3,
    contextAlphaOnEventIsEnabled: true,
  },
});