JavaScript & React libraryFeaturesClustering

Clustering

āš ļø

Clustering feature can work unstable under Windows platform.

Clustering

Cosmograph’s clustering feature allows you to group nodes together based on a shared attribute, providing a powerful way to organize and visualize complex networks. This can help in identifying communities, categorizing data, and simplifying the graph’s appearance.

Enabling clustering

To enable clustering, you need to specify which column in your points data defines the cluster for each point. This is done through the pointClusterBy property in the CosmographConfig.

const config: CosmographConfig = {
  // ... other properties
  pointClusterBy: 'group', // 'group' is the column name in the data
}

The values in the pointClusterBy column can be strings or numbers. Cosmograph will automatically group all points that have the same value in this column into a single cluster.

The clustered layout, where points are physically grouped together, is only visible when the force-directed simulation is active. If the simulation is disabled, points will be positioned based on their coordinates, but clustering data can still be used for labels and coloring.

Dynamic clustering with pointClusterByFn

For more advanced scenarios, you can use pointClusterByFn to dynamically generate cluster assignments. This function overrides the values in the pointClusterBy column by processing them. It receives the value from the pointClusterBy column and an optional index.

pointClusterByFn: (value: any, index?: number) => unknown

Advanced example

The index parameter allows you to access the original data array to perform more complex calculations. For example, you could create clusters based on multiple properties of your data points.

// Assuming `points` is an array of objects available in the component's scope
const points = [
  { id: 'a', category: 'A', value: 12 },
  { id: 'b', category: 'A', value: 25 },
  { id: 'c', category: 'B', value: 8 },
  { id: 'd', category: 'B', value: 30 },
];
 
const config: CosmographConfig = {
  pointClusterBy: 'category', // This value is passed as the first argument to the function
  pointClusterByFn: (category, index) => {
    const point = points[index]; // Access the full data point
    // Create a new cluster for high-value points in each category
    if (point.value > 20) {
      return `High-Value ${point.category}`;
    }
    // Otherwise, use the original category as the cluster
    return category;
  },
}

Controlling cluster positions

The properties described in this section only affect the layout when the force-directed simulation is enabled.

By default, Cosmograph positions clusters at the center of mass of their member points. However, you can manually control their positions.

clusterPositionsMap

The clusterPositionsMap property allows you to specify fixed [x, y] coordinates for each cluster. This is useful for creating consistent layouts or arranging clusters in a specific way.

<Cosmograph
  // ... other props
  clusterPositionsMap={{
    'Rock': [100, 200],
    'Rap': [300, 400],
  }}
/>

Any clusters not present in the map will be positioned automatically.

pointClusterStrengthBy

You can influence how strongly a point is pulled towards its cluster’s center during the force simulation. Provide a column name to pointClusterStrengthBy that contains numeric values (from 0.0 to 1.0). Higher values result in a stronger attraction.

const config: CosmographConfig = {
  pointClusterBy: 'group',
  pointClusterStrengthBy: 'attraction_force', // Column with values 0.0-1.0
}

simulationClusterStrength

The simulationClusterStrength prop is a number between 0 and 1 that applies a uniform clustering force to all points. A higher value will pull points more strongly toward their cluster center. This is useful when you don’t have a specific data column for cluster strength.

<Cosmograph
  // ... other props
  simulationClusterStrength={0.8}
/>

Cluster labels

šŸ’”

The showLabels property (that is enabled by default) globally enables or disables all labels. It must be set to true for other label settings, such as showClusterLabels, to take effect.

Cosmograph can display labels for each cluster, which is essential for understanding the grouped data.

Displaying cluster labels

To display cluster labels, set the showClusterLabels prop to true.

<Cosmograph
  // ... other props
  showClusterLabels={true}
/>

Cluster labels take priority over individual point labels. When a point is selected, cluster labels are hidden to focus on the selection.

Interactivity

You can control how users interact with cluster labels through these props:

NameTypeDescription
selectClusterOnLabelClickbooleanWhen true, clicking a cluster label will select all the points belonging to that cluster.
onClusterLabelClick(index: number, id: string, event: MouseEvent) => voidCallback function that is triggered when a cluster label is clicked. It receives the clusterIndex, clusterId, and the MouseEvent.
const handleClusterClick = (clusterIndex, clusterId, event) => {
  console.log(`Cluster "${clusterId}" with index ${clusterIndex} was clicked.`);
};
 
<Cosmograph
  // ... other props
  selectClusterOnLabelClick={true}
  onClusterLabelClick={handleClusterClick}
/>

Customizing label appearance

You can customize the appearance of cluster labels with the following props:

NameTypeDescription
clusterLabelFontSizenumberSets the font size of the labels. The final size might be adjusted based on scaleClusterLabels.
clusterLabelClassNamestring | (text: string, clusterIndex: number) => stringA string or function to apply a CSS class to the labels for custom styling.
scaleClusterLabelsbooleanA boolean (true by default) that scales the label font size based on the number of points in the cluster.
usePointColorStrategyForClusterLabelsbooleanA boolean that, when true, applies the same color strategy used for points to the cluster labels. This is useful when points are colored by the same data used for clustering.
<Cosmograph
  // ... other props
  showClusterLabels={true}
  clusterLabelFontSize={18}
  scaleClusterLabels={true}
  usePointColorStrategyForClusterLabels={true}
/>

Accessing cluster data (API)

NameTypeDescription
cosmograph.clusterMappingMap<string, { index: number; count: number }>A getter that returns a Map containing information about each cluster, including its index and the number of points it contains.
cosmograph.getClusterPositions()() => number[] | undefinedA method that returns a flattened array of [x, y] coordinates for each cluster.

Example: Dynamic Label Visibility

Here is a common use case: showing cluster labels when zoomed out and individual point labels when zoomed in.

import React, { useEffect, useRef, useState, useCallback } from 'react'
import { CosmographProvider, Cosmograph, CosmographConfig, CosmographRef } from '@cosmograph/react'
 
export const MyGraph = (): JSX.Element => {
  const cosmograph = useRef<CosmographRef>(null)
  const [config, setConfig] = useState<CosmographConfig>({
    // Initial config here
  })
 
  // Data loading logic...
 
  const switchLabelsVisibility = useCallback(() => {
    const zoom = cosmograph.current?.getZoomLevel()
    if (zoom && zoom > 1.5) {
      setConfig({
        ...config,
        showDynamicLabels: true,
        showTopLabels: true,
        showClusterLabels: false,
      })
    } else {
      setConfig({
        ...config,
        showDynamicLabels: false,
        showTopLabels: false,
        showClusterLabels: true,
      })
    }
  }, [config])
 
  return (
    <CosmographProvider>
      <Cosmograph
        ref={cosmograph}
        onZoom={switchLabelsVisibility}
        {...config}
      />
    </CosmographProvider>
  )
}

Check out this example for a complete implementation and demonstration of other cluster features.