BubbleSets

Reading needs 5 minutes

BubbleSets was originally proposed by Christopher Collins in the 2009 paper "Bubble Sets: Revealing Set Relations with Isocontours over Existing Visualizations".

The principle is to represent sets by creating a shape similar to a bubble. Each set is represented by a unique "bubble", and the elements in the set are contained within this bubble. If two sets have an intersection, then the two bubbles will have an overlapping part, which represents the intersection of the two sets.

createGraph(
{
autoFit: 'center',
data: {
nodes: [
{
id: 'node-0',
data: { cluster: 'a' },
style: { x: 555, y: 151 },
},
{
id: 'node-1',
data: { cluster: 'a' },
style: { x: 532, y: 323 },
},
{
id: 'node-2',
data: { cluster: 'a' },
style: { x: 473, y: 227 },
},
{
id: 'node-3',
data: { cluster: 'a' },
style: { x: 349, y: 212 },
},
{
id: 'node-4',
data: { cluster: 'b' },
style: { x: 234, y: 201 },
},
{
id: 'node-5',
data: { cluster: 'b' },
style: { x: 338, y: 333 },
},
{
id: 'node-6',
data: { cluster: 'b' },
style: { x: 365, y: 91 },
},
],
edges: [
{
id: 'edge-0',
source: 'node-0',
target: 'node-2',
},
{
id: 'edge-1',
source: 'node-1',
target: 'node-2',
},
{
id: 'edge-2',
source: 'node-2',
target: 'node-3',
},
{
id: 'edge-3',
source: 'node-3',
target: 'node-4',
},
{
id: 'edge-4',
source: 'node-3',
target: 'node-5',
},
{
id: 'edge-5',
source: 'node-3',
target: 'node-6',
},
],
},
node: {
style: { labelText: (d) => d.id },
palette: { field: 'cluster', color: ['#7e3feb', '#ffa940'] },
},
behaviors: ['drag-canvas', 'drag-element'],
plugins: [
'grid-line',
{
type: 'bubble-sets',
key: 'bubble-sets',
members: ['node-0', 'node-1', 'node-2', 'node-3'],
labelText: 'bubblesets-a',
fill: '#7e3feb',
fillOpacity: 0.1,
stroke: '#7e3feb',
strokeOpacity: 1,
labelFill: '#fff',
labelPadding: 2,
labelBackgroundFill: '#7e3feb',
labelBackgroundRadius: 5,
},
],
},
{ width: 600, height: 450 },
(gui, graph) => {
const options = {
type: 'bubble-sets',
members: ['node-0', 'node-1', 'node-2', 'node-3'],
avoidMembers: [],
// style
fill: '#7e3feb',
fillOpacity: 0.1,
stroke: '#7e3feb',
strokeOpacity: 1,
// label
label: true,
labelCloseToPath: true,
labelAutoRotate: true,
labelOffsetX: 0,
labelOffsetY: 0,
labelPlacement: 'bottom',
// bubblesets
maxRoutingIterations: 100,
maxMarchingIterations: 20,
pixelGroup: 4,
edgeR0: 10,
edgeR1: 20,
nodeR0: 15,
nodeR1: 50,
morphBuffer: 10,
threshold: 1,
memberInfluenceFactor: 1,
edgeInfluenceFactor: 1,
nonMemberInfluenceFactor: -0.8,
virtualEdges: true,
};
const optionFolder = gui.addFolder('Bubblesets Options');
optionFolder.add(options, 'type').disable();
optionFolder.addColor(options, 'fill');
optionFolder.addColor(options, 'stroke');
optionFolder.add(options, 'fillOpacity', 0, 1, 0.1);
optionFolder.add(options, 'strokeOpacity', 0, 1, 0.1);
optionFolder.add(options, 'label');
optionFolder.add(options, 'labelCloseToPath');
optionFolder.add(options, 'labelAutoRotate');
optionFolder.add(options, 'labelOffsetX', 0, 20, 1);
optionFolder.add(options, 'labelOffsetY', 0, 20, 1);
optionFolder.add(options, 'labelPlacement', ['left', 'right', 'top', 'bottom', 'center']);
optionFolder.add(options, 'maxRoutingIterations', 0, 200, 1);
optionFolder.add(options, 'maxMarchingIterations', 0, 40, 1);
optionFolder.add(options, 'pixelGroup', 0, 20, 1);
optionFolder.add(options, 'edgeR0', 0, 50, 1);
optionFolder.add(options, 'edgeR1', 0, 50, 1);
optionFolder.add(options, 'nodeR0', 0, 50, 1);
optionFolder.add(options, 'nodeR1', 0, 50, 1);
optionFolder.add(options, 'morphBuffer', 0, 20, 1);
optionFolder.add(options, 'threshold', -1, 1, 0.1);
optionFolder.add(options, 'memberInfluenceFactor', -1, 1, 0.1);
optionFolder.add(options, 'edgeInfluenceFactor', -1, 1, 0.1);
optionFolder.add(options, 'nonMemberInfluenceFactor', -1, 1, 0.1);
optionFolder.add(options, 'virtualEdges');
optionFolder.onChange(({ property, value }) => {
graph.updatePlugin({
key: 'bubble-sets',
[property]: value,
});
graph.render();
});
const apiConfig = {
member: 'node-1',
avoidMember: 'node-1',
};
const apiFolder = gui.addFolder('Bubblesets API');
const instance = graph.getPluginInstance('bubble-sets');
const nodeIds = graph.getData().nodes.map((node) => node.id);
const edgeIds = graph.getData().edges.map((edge) => edge.id);
apiFolder.add(apiConfig, 'member', [...nodeIds, ...edgeIds]);
apiFolder.add({ addMember: () => instance.addMember(apiConfig.member) }, 'addMember').name('add member');
apiFolder
.add({ removeMember: () => instance.removeMember(apiConfig.member) }, 'removeMember')
.name('remove member');
apiFolder
.add({ removeMember: () => alert('Members in Bubblesets: ' + instance.getMember()) }, 'removeMember')
.name('get member');
apiFolder.add(apiConfig, 'avoidMember', nodeIds);
apiFolder
.add({ addAvoidMember: () => instance.addAvoidMember(apiConfig.avoidMember) }, 'addAvoidMember')
.name('add avoid member');
apiFolder
.add({ removeAvoidMember: () => instance.removeAvoidMember(apiConfig.avoidMember) }, 'removeAvoidMember')
.name('remove avoid member');
apiFolder
.add({ removeMember: () => alert('Avoid members in Bubblesets: ' + instance.getAvoidMember()) }, 'removeMember')
.name('get avoid member');
},
);

Options

Required type

bubble-sets

Plugin type

label

boolean Default: true

Whether to display the label

avoidMembers

string[]

Elements to avoid, these elements will not be included when drawing the contour, currently only nodes are supported

Required members

string[]

Member elements, including nodes and edges

label{TextStyleProps}

An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.

TextStyleProps includes the following properties:

  • fill
  • fontSize
  • fontWeight
  • ...

icon{TextStyleProps} means you need to use the following property names:

  • iconFill
  • iconFontSize
  • iconFontWeight
  • ...

labelAutoRotate

boolean Default: true

Whether the label rotates with the contour. Only effective when closeToPath is true

labelCloseToPath

boolean Default: true

Whether the label is close to the contour

labelMaxWidth

number

The maximum width of the text, which will be automatically ellipsis if exceeded

labelOffsetX

number Default: 0

Label x-axis offset

labelOffsetY

number Default: 0

Label y-axis offset

labelPlacement

'left' | 'right' | 'top' | 'bottom' | 'center' Default: 'bottom'

Label position

labelBackground

boolean

Whether to show background

labelPadding

number | number[] Default: 0

Label padding

Label Background Style

labelBackground{RectStyleProps}

An expression like icon{TextStyleProps} indicates that properties of the TextStyleProps type are prefixed with icon in camelCase format.

TextStyleProps includes the following properties:

  • fill
  • fontSize
  • fontWeight
  • ...

icon{TextStyleProps} means you need to use the following property names:

  • iconFill
  • iconFontSize
  • iconFontWeight
  • ...

API

BubbleSets.addAvoidMember(avoidMembers)

Add elements to avoid

addAvoidMember(avoidMembers: ID | ID[]): void;
View Parameters

Parameter

Type

Description

avoidMembers

string | string[]

单个或多个

Returns:

  • Type: void

BubbleSets.addMember(members)

Add member elements

addMember(members: ID | ID[]): void;
View Parameters

Parameter

Type

Description

members

string | string[]

单个或多个

Returns:

  • Type: void

BubbleSets.getAvoidMember()

Get elements to avoid

getAvoidMember(): string[];
View Parameters

Returns:

  • Type: string[]

  • Description: 成员元素数组

BubbleSets.getMember()

Get member elements

getMember(): string[];
View Parameters

Returns:

  • Type: string[]

  • Description: 成员元素数组

BubbleSets.removeAvoidMember(avoidMembers)

Remove elements to avoid

removeAvoidMember(avoidMembers: ID | ID[]): void;
View Parameters

Parameter

Type

Description

avoidMembers

string | string[]

单个或多个

Returns:

  • Type: void

BubbleSets.removeMember(members)

Remove member elements

removeMember(members: ID | ID[]): void;
View Parameters

Parameter

Type

Description

members

string | string[]

单个或多个

Returns:

  • Type: void

BubbleSets.updateAvoidMember(avoidMembers)

Update elements to avoid

updateAvoidMember(avoidMembers: ID | ID[]): void;
View Parameters

Parameter

Type

Description

avoidMembers

string | string[]

单个或多个

Returns:

  • Type: void

BubbleSets.updateMember(members)

Update member elements

updateMember(members: ID[] | ((prev: ID[]) => ID[])): void;
View Parameters

Parameter

Type

Description

members

string[] | ((prev: string[]) => string[])

值或者回调函数

Returns:

  • Type: void
Previous
Background
Next
CameraSetting