mirror of
https://gitee.com/antv/g6.git
synced 2024-11-30 02:38:20 +08:00
docs(site): update layout examples (#5728)
* refactor: adjust layout api and exports * chore: update deploy actions * docs(site): update layout examples
This commit is contained in:
parent
454bc13e09
commit
352b5ba1c6
10
.github/workflows/deploy.yml
vendored
10
.github/workflows/deploy.yml
vendored
@ -4,7 +4,7 @@ on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- v5
|
||||
- v5
|
||||
|
||||
jobs:
|
||||
deploy-site:
|
||||
@ -16,10 +16,14 @@ jobs:
|
||||
node-version: 18
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
version: 8
|
||||
- uses: actions/checkout@v2
|
||||
- run: pnpm install
|
||||
- run: npx turbo build
|
||||
- run: |
|
||||
cd ./packages/site
|
||||
pnpm run doc
|
||||
pnpm run build
|
||||
- run: cp ./packages/site/CNAME ./packages/site/dist/CNAME
|
||||
- run: |
|
||||
cd ./packages/site/dist
|
||||
@ -33,4 +37,4 @@ jobs:
|
||||
github_token: ${{secrets.PERSONAL_ACCESS_TOKEN}}
|
||||
directory: ./packages/site/dist
|
||||
branch: v5-site
|
||||
force: true
|
||||
force: true
|
||||
|
@ -79,6 +79,7 @@ export { getExtension, getExtensions, register } from './registry';
|
||||
export { Graph } from './runtime/graph';
|
||||
export { BaseTransform } from './transforms';
|
||||
export { idOf } from './utils/id';
|
||||
export { invokeLayoutMethod } from './utils/layout';
|
||||
export { omitStyleProps, subStyleProps } from './utils/prefix';
|
||||
export { Shortcut } from './utils/shortcut';
|
||||
export { parseSize } from './utils/size';
|
||||
|
@ -893,8 +893,8 @@ export class Graph extends EventEmitter {
|
||||
* <en/> Execute layout
|
||||
* @apiCategory layout
|
||||
*/
|
||||
public layout() {
|
||||
this.context.layout!.layout();
|
||||
public async layout() {
|
||||
await this.context.layout!.layout();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -203,9 +203,9 @@ export function layoutAdapter(
|
||||
*
|
||||
* <en/> Call layout member methods
|
||||
* @description
|
||||
* <zh/> 提供一种通用的调用方式来调用 G6 布局和 @antv/layout 布局上的方法
|
||||
* <zh/> 提供一种通用的调用方式来调用 G6 布局和 \@antv/layout 布局上的方法
|
||||
*
|
||||
* <en/> Provide a common way to call methods on G6 layout and @antv/layout layout
|
||||
* <en/> Provide a common way to call methods on G6 layout and \@antv/layout layout
|
||||
* @param layout - <zh/> 布局实例 | <en/> Layout instance
|
||||
* @param method - <zh/> 方法名 | <en/> Method name
|
||||
* @param args - <zh/> 参数 | <en/> Arguments
|
||||
|
@ -1,174 +0,0 @@
|
||||
import { Graph, Extensions, extend } from '@antv/g6';
|
||||
|
||||
const edgeClusterTransform = (dataAUR = {}, options = {}, graphCore) => {
|
||||
const { dataAdded, dataUpdated, dataRemoved } = dataAUR;
|
||||
const handler = (data = {}, options = {}, core) => {
|
||||
const { nodes = [], edges = [] } = data;
|
||||
const nodeMap = new Map();
|
||||
graphCore?.getAllNodes().forEach((node) => nodeMap.set(node.id, node));
|
||||
nodes.forEach((node) => nodeMap.set(node.id, node));
|
||||
edges.forEach((edge) => {
|
||||
edge.data.cluster = nodeMap.get(edge.source)?.data.cluster;
|
||||
});
|
||||
return data;
|
||||
};
|
||||
return {
|
||||
dataAdded: handler(dataAdded, options, graphCore),
|
||||
dataUpdated: handler(dataUpdated, options, graphCore),
|
||||
dataRemoved: dataRemoved,
|
||||
};
|
||||
};
|
||||
class LineLayout {
|
||||
// implements Layout<{}>
|
||||
id = 'line-layout';
|
||||
|
||||
constructor(options = {}) {
|
||||
this.options = options;
|
||||
}
|
||||
/**
|
||||
* Return the positions of nodes and edges(if needed).
|
||||
*/
|
||||
async execute(graph, options = {}) {
|
||||
return this.genericLineLayout(false, graph, options);
|
||||
}
|
||||
/**
|
||||
* To directly assign the positions to the nodes.
|
||||
*/
|
||||
async assign(graph, options = {}) {
|
||||
this.genericLineLayout(true, graph, options);
|
||||
}
|
||||
|
||||
async genericLineLayout(assign, graph, options = {}) {
|
||||
const { height = 500 } = { ...this.options, ...options };
|
||||
|
||||
const nodes = graph.getAllNodes();
|
||||
const edges = graph.getAllEdges();
|
||||
const layoutNodes = [];
|
||||
let x = 10;
|
||||
let lastNodeRadius = 0;
|
||||
nodes.forEach((node, i) => {
|
||||
const currentRadius = node.data.keyShape?.r || 16;
|
||||
if (i > 0) {
|
||||
x = layoutNodes[i - 1].data.x + lastNodeRadius + currentRadius + 4;
|
||||
}
|
||||
layoutNodes.push({
|
||||
id: node.id,
|
||||
data: {
|
||||
x,
|
||||
y: height * 0.7,
|
||||
},
|
||||
});
|
||||
lastNodeRadius = currentRadius;
|
||||
});
|
||||
const result = {
|
||||
nodes: layoutNodes,
|
||||
edges,
|
||||
};
|
||||
|
||||
if (assign) {
|
||||
layoutNodes.forEach((node) => {
|
||||
graph.mergeNodeData(node.id, {
|
||||
x: node.data.x,
|
||||
y: node.data.y,
|
||||
});
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
const container = document.getElementById('container');
|
||||
const width = container.scrollWidth;
|
||||
const height = container.scrollHeight || 500;
|
||||
|
||||
const ExtGraph = extend(Graph, {
|
||||
edges: {
|
||||
'quadratic-edge': Extensions.QuadraticEdge,
|
||||
},
|
||||
transforms: {
|
||||
'edge-cluster': edgeClusterTransform,
|
||||
'transform-v4-data': Extensions.TransformV4Data,
|
||||
},
|
||||
layouts: {
|
||||
'line-layout': LineLayout,
|
||||
},
|
||||
});
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/70cde3be-22e8-4291-98f1-4d5a5b75b62f.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new ExtGraph({
|
||||
container: 'container',
|
||||
width,
|
||||
height,
|
||||
autoFit: 'view',
|
||||
transforms: ['transform-v4-data', 'edge-cluster'],
|
||||
plugins: [
|
||||
{
|
||||
type: 'lod-controller',
|
||||
disableLod: true,
|
||||
},
|
||||
],
|
||||
layout: { type: 'line-layout' },
|
||||
theme: {
|
||||
type: 'spec',
|
||||
specification: {
|
||||
node: {
|
||||
dataTypeField: 'cluster',
|
||||
},
|
||||
edge: {
|
||||
dataTypeField: 'cluster',
|
||||
},
|
||||
},
|
||||
},
|
||||
node: {
|
||||
keyShape: {
|
||||
r: 8,
|
||||
},
|
||||
labelShape: {
|
||||
text: {
|
||||
fields: ['name'],
|
||||
formatter: (model) => model.data.name,
|
||||
},
|
||||
angle: Math.PI / 2,
|
||||
textAlign: 'left',
|
||||
offsetX: 10,
|
||||
maxWidth: 100,
|
||||
},
|
||||
anchorPoints: [[0.5, 0]],
|
||||
},
|
||||
edge: {
|
||||
type: 'quadratic-edge',
|
||||
keyShape: {
|
||||
opacity: 0.4,
|
||||
},
|
||||
},
|
||||
modes: {
|
||||
default: ['click-select', 'drag-canvas', 'drag-node'],
|
||||
},
|
||||
data,
|
||||
});
|
||||
|
||||
graph.on('afterlayout', (e) => {
|
||||
const edgeDatas = graph.getAllEdgesData().map((edge) => {
|
||||
const { id, source, target } = edge;
|
||||
const sourceData = graph.getNodeData(source);
|
||||
const targetData = graph.getNodeData(target);
|
||||
const [width, height] = graph.getSize();
|
||||
const xSep = (width - 20) / graph.getAllNodesData().length;
|
||||
const endsSepStep = (targetData.data.x - sourceData.data.x) / xSep;
|
||||
const sign = endsSepStep < 0 ? 1 : -1;
|
||||
return {
|
||||
id,
|
||||
data: {
|
||||
keyShape: {
|
||||
curveOffset: ((sign * width) / 55) * Math.ceil(Math.abs(endsSepStep)),
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
graph.updateData('edge', edgeDatas);
|
||||
});
|
||||
|
||||
window.graph = graph;
|
||||
});
|
@ -1,135 +0,0 @@
|
||||
import { Graph, Extensions, extend } from '@antv/g6';
|
||||
|
||||
const container = document.getElementById('container');
|
||||
const width = container.scrollWidth;
|
||||
const height = container.scrollHeight || 500;
|
||||
|
||||
const edgeClusterTransform = (data = {}, options = {}, graphCore) => {
|
||||
const { dataAdded, dataUpdated, dataRemoved } = data;
|
||||
const handler = (data = {}, options = {}, core) => {
|
||||
const { nodes = [], edges = [] } = data;
|
||||
const nodeMap = new Map();
|
||||
nodes.forEach((node) => nodeMap.set(node.id, node));
|
||||
edges.forEach((edge) => {
|
||||
edge.data.cluster = nodeMap.get(edge.source).data.cluster;
|
||||
});
|
||||
return data;
|
||||
};
|
||||
return {
|
||||
dataAdded: handler(dataAdded, options, graphCore),
|
||||
dataUpdated: handler(dataUpdated, options, graphCore),
|
||||
dataRemoved: handler(dataRemoved, options, graphCore),
|
||||
};
|
||||
};
|
||||
|
||||
const ExtGraph = extend(Graph, {
|
||||
transforms: {
|
||||
'edge-cluster': edgeClusterTransform,
|
||||
'transform-v4-data': Extensions.TransformV4Data,
|
||||
'map-node-size': Extensions.MapNodeSize,
|
||||
},
|
||||
edges: {
|
||||
'quadratic-edge': Extensions.QuadraticEdge,
|
||||
},
|
||||
});
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/70cde3be-22e8-4291-98f1-4d5a5b75b62f.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new ExtGraph({
|
||||
container: 'container',
|
||||
width,
|
||||
height,
|
||||
transforms: [
|
||||
'transform-v4-data',
|
||||
{
|
||||
type: 'map-node-size',
|
||||
field: 'value',
|
||||
},
|
||||
'edge-cluster',
|
||||
],
|
||||
plugins: [
|
||||
{
|
||||
type: 'lod-controller',
|
||||
disableLod: true,
|
||||
},
|
||||
],
|
||||
layout: {
|
||||
type: 'circular',
|
||||
},
|
||||
theme: {
|
||||
type: 'spec',
|
||||
specification: {
|
||||
node: {
|
||||
dataTypeField: 'cluster',
|
||||
},
|
||||
edge: {
|
||||
dataTypeField: 'cluster',
|
||||
},
|
||||
},
|
||||
},
|
||||
node: (model) => {
|
||||
return {
|
||||
id: model.id,
|
||||
data: {
|
||||
...model.data,
|
||||
labelShape: {
|
||||
position: 'right',
|
||||
textAlign: 'left',
|
||||
offsetX: 0,
|
||||
offsetY: 0,
|
||||
...model.data.labelShape,
|
||||
text: model.data.name,
|
||||
maxWidth: 100,
|
||||
},
|
||||
animates: {
|
||||
update: [
|
||||
{
|
||||
fields: ['opacity'],
|
||||
shapeId: 'haloShape',
|
||||
},
|
||||
{
|
||||
fields: ['lineWidth'],
|
||||
shapeId: 'keyShape',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
edge: {
|
||||
type: 'quadratic-edge',
|
||||
keyShape: {
|
||||
opacity: 0.4,
|
||||
controlPoints: [{ x: width / 2, y: height / 2 }],
|
||||
},
|
||||
},
|
||||
modes: {
|
||||
default: ['drag-node', 'click-select', 'zoom-canvas', 'drag-canvas'],
|
||||
},
|
||||
data,
|
||||
});
|
||||
graph.on('afterlayout', (e) => {
|
||||
const angleUpdates = graph.getAllNodesData().map((node) => {
|
||||
const { x, y } = node.data;
|
||||
const vecX = x - width / 2;
|
||||
const vecY = y - height / 2;
|
||||
const dist = Math.sqrt(vecX * vecX + vecY * vecY);
|
||||
let angle = Math.asin(vecY / dist);
|
||||
if (vecX < 0) angle = -angle;
|
||||
return {
|
||||
id: node.id,
|
||||
data: {
|
||||
labelShape: {
|
||||
position: vecX < 0 ? 'center' : 'right',
|
||||
textAlign: vecX < 0 ? 'right' : 'left',
|
||||
angle,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
graph.updateData('node', angleUpdates);
|
||||
graph.fitView();
|
||||
});
|
||||
window.graph = graph;
|
||||
});
|
@ -1,24 +0,0 @@
|
||||
{
|
||||
"title": {
|
||||
"zh": "中文分类",
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicArcDiagram.js",
|
||||
"title": {
|
||||
"zh": "基本弧线图",
|
||||
"en": "Basic Arc Diagram"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*_eivQrJXt8sAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "circularArcDiagram.js",
|
||||
"title": {
|
||||
"zh": "环形弧线图",
|
||||
"en": "Circular Arc Diagram"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*o-tESYnAAJYAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Arc Diagram
|
||||
order: 9
|
||||
---
|
||||
|
||||
Arc diagram is a method of graph visualization. It places the nodes on one axis, and connects the nodes by arcs.
|
||||
|
||||
## Usage
|
||||
|
||||
- Example 1 : Place the node positions to an axis, and calculate the heights of the arcs according to the distances between endpoints.
|
||||
- Example 2 : Circular Arc Diagram is a deformation of Arc Diagram. In this example, the nodes are placed on a circle, the edges are quadratic bezier curves.
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Arc Diagram 弧线图
|
||||
order: 9
|
||||
---
|
||||
|
||||
弧线图是一种图的可视化形式。其将节点排列在一个轴上,边以弧线的形式连接节点。
|
||||
|
||||
## 使用指南
|
||||
|
||||
- 代码演示 1 :通过指定节点位置,并根据节点间距计算 arc 弧线类型边的弧高度可以实现基础弧线图。
|
||||
- 代码演示 2 :指定节点位置到圆环上,使用 quadratic 二阶贝塞尔曲线类型的边实现了弧线图的变种 —— 环形弧线图。
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/circular.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/circular.zh.md"></embed>
|
25
packages/site/examples/layout/circular/demo/basic.js
Normal file
25
packages/site/examples/layout/circular/demo/basic.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/circular.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -1,403 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
label: '0',
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
label: '6',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
label: '7',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
label: '8',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
label: '9',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
label: '11',
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
label: '12',
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
label: '13',
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
label: '14',
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
label: '15',
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
label: '16',
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
label: '17',
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
label: '18',
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
label: '19',
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
label: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
label: '23',
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
label: '24',
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
label: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
label: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
label: '27',
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
label: '28',
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
label: '29',
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
label: '31',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '32',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
label: '33',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -1,517 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
label: '0',
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
label: '6',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
label: '7',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
label: '8',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
label: '9',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
label: '11',
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
label: '12',
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
label: '13',
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
label: '14',
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
label: '15',
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
label: '16',
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
label: '17',
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
label: '18',
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
label: '19',
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
label: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
label: '23',
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
label: '24',
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
label: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
label: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
label: '27',
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
label: '28',
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
label: '29',
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
label: '31',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '32',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
label: '33',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const descriptionDiv = document.createElement('div');
|
||||
descriptionDiv.innerHTML = 'Circular layout with radius: take full use of the canvas, ordering: topology';
|
||||
const container = document.getElementById('container') as HTMLDivElement;
|
||||
container.appendChild(descriptionDiv);
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
layout: {
|
||||
type: 'circular',
|
||||
},
|
||||
data,
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: {
|
||||
path: 'M 0,0 L 8,4 L 8,-4 Z',
|
||||
fill: '#e2e2e2',
|
||||
},
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
animation: true,
|
||||
});
|
||||
graph.render();
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('error', () => {
|
||||
if (time) {
|
||||
clearInterval(time);
|
||||
}
|
||||
});
|
||||
window.onresize = () => {
|
||||
if (!graph || graph.destroyed) return;
|
||||
if (!container || !container.scrollWidth || !container.scrollHeight) return;
|
||||
graph.resize(container.scrollWidth, container.scrollHeight - 30);
|
||||
};
|
||||
}
|
||||
|
||||
layoutConfigTranslation();
|
||||
|
||||
const time = setInterval(function () {
|
||||
layoutConfigTranslation();
|
||||
}, 11500);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param layoutConfig
|
||||
*/
|
||||
function updateLayout(layoutConfig) {
|
||||
graph.setLayout((current) => ({
|
||||
...current,
|
||||
...layoutConfig,
|
||||
}));
|
||||
graph.render();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function layoutConfigTranslation() {
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML = 'Circular layout, radius = 200, divisions = 5, ordering: degree';
|
||||
updateLayout({
|
||||
radius: 200,
|
||||
startAngle: Math.PI / 4,
|
||||
endAngle: Math.PI,
|
||||
divisions: 5,
|
||||
ordering: 'degree',
|
||||
});
|
||||
}, 1000);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML = 'Circular layout, radius = 200, divisions = 3, ordering: degree';
|
||||
updateLayout({
|
||||
startAngle: Math.PI / 4,
|
||||
endAngle: Math.PI,
|
||||
divisions: 3,
|
||||
});
|
||||
}, 2500);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML = 'Circular layout, radius = 200, divisions = 8, ordering: degree';
|
||||
updateLayout({
|
||||
radius: 200,
|
||||
startAngle: 0,
|
||||
endAngle: Math.PI / 2,
|
||||
divisions: 8,
|
||||
});
|
||||
}, 4000);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML =
|
||||
'Circular layout, radius = 10~300(spiral), endAngle: PI, divisions = 1, ordering: degree';
|
||||
updateLayout({
|
||||
radius: null,
|
||||
startRadius: 10,
|
||||
endRadius: 300,
|
||||
divisions: 1,
|
||||
startAngle: 0,
|
||||
endAngle: Math.PI,
|
||||
});
|
||||
}, 5500);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML =
|
||||
'Circular layout, radius = 10~300(spiral),endAngle: 2 * PI, divisions= 1, ordering: degree';
|
||||
updateLayout({
|
||||
endAngle: 2 * Math.PI,
|
||||
});
|
||||
}, 7000);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML = 'Circular layout, radius = 200, ordering: degree';
|
||||
updateLayout({
|
||||
radius: 200,
|
||||
});
|
||||
}, 8500);
|
||||
|
||||
setTimeout(function () {
|
||||
descriptionDiv.innerHTML = 'Circular layout, radius = 200, ordering: topology';
|
||||
updateLayout({
|
||||
radius: 200,
|
||||
ordering: 'topology',
|
||||
});
|
||||
}, 10000);
|
||||
}
|
27
packages/site/examples/layout/circular/demo/degree.js
Normal file
27
packages/site/examples/layout/circular/demo/degree.js
Normal file
@ -0,0 +1,27 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/circular.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
ordering: 'degree',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -1,405 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
label: '0',
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
label: '6',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
label: '7',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
label: '8',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
label: '9',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
label: '11',
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
label: '12',
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
label: '13',
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
label: '14',
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
label: '15',
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
label: '16',
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
label: '17',
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
label: '18',
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
label: '19',
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
label: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
label: '23',
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
label: '24',
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
label: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
label: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
label: '27',
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
label: '28',
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
label: '29',
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
label: '31',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '32',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
label: '33',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
ordering: 'degree',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
33
packages/site/examples/layout/circular/demo/division.js
Normal file
33
packages/site/examples/layout/circular/demo/division.js
Normal file
@ -0,0 +1,33 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/circular.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
divisions: 5,
|
||||
radius: 200,
|
||||
startAngle: Math.PI / 4,
|
||||
endAngle: Math.PI,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: true,
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -1,415 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
label: '0',
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
label: '6',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
label: '7',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
label: '8',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
label: '9',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
label: '11',
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
label: '12',
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
label: '13',
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
label: '14',
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
label: '15',
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
label: '16',
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
label: '17',
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
label: '18',
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
label: '19',
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
label: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
label: '23',
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
label: '24',
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
label: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
label: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
label: '27',
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
label: '28',
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
label: '29',
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
label: '31',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '32',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
label: '33',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
divisions: 5,
|
||||
radius: 200,
|
||||
startAngle: Math.PI / 4,
|
||||
endAngle: Math.PI,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: {
|
||||
path: 'M 0,0 L 8,4 L 8,-4 Z',
|
||||
fill: '#e2e2e2',
|
||||
},
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -5,7 +5,7 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basic.ts",
|
||||
"filename": "basic.js",
|
||||
"title": {
|
||||
"zh": "基本 Circular 布局",
|
||||
"en": "Basic Circular Layout"
|
||||
@ -13,15 +13,15 @@
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*ZSuXQ4PS2F8AAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "degree.ts",
|
||||
"filename": "degree.js",
|
||||
"title": {
|
||||
"zh": "按照节点度数排序的 Circular 布局",
|
||||
"en": "Degree Ordered Circular"
|
||||
"zh": "按照节点度数排序",
|
||||
"en": "Degree Ordered"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*MOEeS6ooB7AAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "spiral.ts",
|
||||
"filename": "spiral.js",
|
||||
"title": {
|
||||
"zh": "螺旋线布局",
|
||||
"en": "Spiral Layout"
|
||||
@ -29,20 +29,12 @@
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*bY0iSqTc3z4AAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "division.ts",
|
||||
"filename": "division.js",
|
||||
"title": {
|
||||
"zh": "分割环形布局",
|
||||
"en": "Divided Circular Layout"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*u30nQahg6q0AAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "configurationTranslate.ts",
|
||||
"title": {
|
||||
"zh": "Circular 布局参数动态变化",
|
||||
"en": "Update Configurations for Circular Layout"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*D85cS7-yqNEAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
32
packages/site/examples/layout/circular/demo/spiral.js
Normal file
32
packages/site/examples/layout/circular/demo/spiral.js
Normal file
@ -0,0 +1,32 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/circular.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
startRadius: 10,
|
||||
endRadius: 300,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: true,
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -1,414 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
label: '0',
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
label: '1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
label: '2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
label: '3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
label: '4',
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
label: '5',
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
label: '6',
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
label: '7',
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
label: '8',
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
label: '9',
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
label: '10',
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
label: '11',
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
label: '12',
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
label: '13',
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
label: '14',
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
label: '15',
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
label: '16',
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
label: '17',
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
label: '18',
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
label: '19',
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
label: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
label: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
label: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
label: '23',
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
label: '24',
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
label: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
label: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
label: '27',
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
label: '28',
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
label: '29',
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
label: '30',
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
label: '31',
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
label: '32',
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
label: '33',
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'circular',
|
||||
startRadius: 10,
|
||||
endRadius: 300,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
fill: '#EFF4FF',
|
||||
lineWidth: 1,
|
||||
stroke: '#5F95FF',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: {
|
||||
path: 'M 0,0 L 8,4 L 8,-4 Z',
|
||||
fill: '#e2e2e2',
|
||||
},
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -1,16 +1,4 @@
|
||||
---
|
||||
title: Circular Layout
|
||||
order: 4
|
||||
---
|
||||
|
||||
Circular layout orders the nodes according to the configuration, and then places the nodes on a circle.
|
||||
|
||||
## Usage
|
||||
|
||||
As the demo below, you can deploy it in `layout` while instantiating Graph. it can also be used for [Subgraph Layout](/en/docs/manual/middle/layout/sub-layout). By tuning the configurations, you can adjust the radius, start angle, end angle, nodes' order method, divisions, spiral style, and so on.
|
||||
|
||||
- Example 1 : Basic Circular Layout, the nodes are placed on the circle clockwise in the data order.
|
||||
- Example 2 : The nodes are placed on the circle clockwise according to their degrees.
|
||||
- Example 3 : Spiral layout.
|
||||
- Example 4 : Divide the nodes into several divisions on the circle.
|
||||
- Example 5 : Translate the parameters in dynamic.
|
||||
---
|
@ -1,16 +1,4 @@
|
||||
---
|
||||
title: Circular 环形布局
|
||||
order: 4
|
||||
---
|
||||
|
||||
Circular 环形布局根据参数指定的排序方式对节点进行排序后,将节点排列在圆环上。
|
||||
|
||||
## 使用指南
|
||||
|
||||
G6 内置的 Circular 环形布局可在实例化 Graph 时使用该布局。除此之外,还可以如[子图布局](/zh/docs/manual/middle/layout/sub-layout)所示单独使用布局。该布局可以通过配置调整半径、起始和结束角度、节点排序方式、节点分组、螺旋线布局等。
|
||||
|
||||
- 代码演示 1 :基本的环形布局,节点根据在数据中的顺序逆时针排列。
|
||||
- 代码演示 2 :节点根据其度数从大到小逆时针排列。
|
||||
- 代码演示 3 :螺旋线布局。
|
||||
- 代码演示 4 :分组圆环布局。
|
||||
- 代码演示 5 :圆环布局参数动态变化。
|
||||
---
|
@ -0,0 +1,37 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/combo.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'combo-combined',
|
||||
comboPadding: 2,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: (d) => d.combo,
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: (model) => {
|
||||
const { size, color } = model.data;
|
||||
return {
|
||||
stroke: color || '#99ADD1',
|
||||
lineWidth: size || 1,
|
||||
};
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],
|
||||
autoFit: 'view',
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -5,7 +5,7 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "comboCombined.ts",
|
||||
"filename": "combo-combined.js",
|
||||
"title": {
|
||||
"zh": "ComboCombined 组合布局",
|
||||
"en": "Combo Combined Layout"
|
4
packages/site/examples/layout/combo-layout/index.en.md
Normal file
4
packages/site/examples/layout/combo-layout/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Combo Layout
|
||||
order: 2
|
||||
---
|
4
packages/site/examples/layout/combo-layout/index.zh.md
Normal file
4
packages/site/examples/layout/combo-layout/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: 组合布局
|
||||
order: 2
|
||||
---
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
## ComboCombined
|
||||
|
||||
<embed src="@/docs/api/graphLayout/comboCombined.en.md"></embed>
|
||||
|
||||
## ComboForce
|
||||
|
||||
<embed src="@/docs/api/graphLayout/comboForce.en.md"></embed>
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
## ComboCombined - Combo 组合布局
|
||||
|
||||
<embed src="@/docs/api/graphLayout/comboCombined.zh.md"></embed>
|
||||
|
||||
## ComboForce - Combo 力导布局
|
||||
|
||||
<embed src="@/docs/api/graphLayout/comboForce.zh.md"></embed>
|
@ -1,572 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
style: {
|
||||
parentId: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
style: {
|
||||
parentId: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
style: {
|
||||
parentId: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
style: {
|
||||
parentId: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
style: {
|
||||
parentId: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
style: {
|
||||
parentId: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
style: {
|
||||
parentId: 'd',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
style: {
|
||||
parentId: 'd',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
// {
|
||||
// id: 'edge-647',
|
||||
// source: 'a',
|
||||
// target: 'b',
|
||||
// data: {
|
||||
// label: 'Combo A - Combo B',
|
||||
// size: 3,
|
||||
// color: 'red',
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// id: 'edge-623',
|
||||
// source: 'a',
|
||||
// target: '33',
|
||||
// data: {
|
||||
// label: 'Combo-Node',
|
||||
// size: 3,
|
||||
// color: 'blue',
|
||||
// },
|
||||
// },
|
||||
{
|
||||
id: 'edge-444',
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
id: 'edge-123',
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
id: 'edge-689',
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-625',
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
id: 'edge-110',
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-783',
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
id: 'edge-72',
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
id: 'edge-165',
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
id: 'edge-109',
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-764',
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
id: 'edge-596',
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-711',
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-81',
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
id: 'edge-810',
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
id: 'edge-957',
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-279',
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-83',
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-488',
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-453',
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-523',
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-543',
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-30',
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-146',
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-878',
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
id: 'edge-369',
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-179',
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-759',
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-116',
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-940',
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-538',
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-522',
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-73',
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
id: 'edge-59',
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-493',
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-162',
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-13',
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-892',
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-722',
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
id: 'edge-617',
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-364',
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-926',
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-31',
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-695',
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-286',
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-300',
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-503',
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
id: 'edge-509',
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
id: 'edge-432',
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-293',
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-785',
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-514',
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-608',
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
id: 'edge-946',
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-728',
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-416',
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
id: 'edge-14',
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
id: 'edge-776',
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-736',
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-508',
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-201',
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
combos: [
|
||||
{
|
||||
id: 'a',
|
||||
data: {
|
||||
label: 'Combo A',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'b',
|
||||
data: {
|
||||
label: 'Combo B',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'c',
|
||||
data: {
|
||||
label: 'Combo D',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'd',
|
||||
data: {
|
||||
label: 'Combo D',
|
||||
parentId: 'b',
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'combo-combined',
|
||||
comboPadding: 2,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: (model) => {
|
||||
const { size, color } = model.data as { size: number; color: string };
|
||||
return {
|
||||
stroke: color || '#99ADD1',
|
||||
lineWidth: size || 1,
|
||||
};
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],
|
||||
autoFit: 'view',
|
||||
});
|
||||
|
||||
graph.render();
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: Combo Related Layout
|
||||
order: 2
|
||||
---
|
||||
|
||||
_New feature of V4.6_ Designed for graph with combos. Support configuring the layout for items inside a combo and the layout for the outer combos and nodes.
|
||||
|
||||
_New feature of V3.5._ Combo Force is designed for the graph with combos based on classical force directed layout algorith. It modifies the forces between nodes according to their combo infomation to achieve a final result with clustering nodes inside each combo and no overlappings.
|
||||
|
||||
## Usage
|
||||
|
||||
We suggest to use `'comboCombined'` or `'comboForce'` for the graph with combos. Other layouts in G6 are also availabel, but they do not consider the combo infomation.
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: Combo 相关布局
|
||||
order: 2
|
||||
---
|
||||
|
||||
*V4.6.0 新增功能。*是 G6 自研的、适用于带有 combo 的图,可自由组合内外布局,默认情况下,内部使用同心圆布局,外部使用力导向布局,可以有较好的效果,推荐有 combo 的图使用该布局。
|
||||
|
||||
*V3.5 新增功能。*Combo Force 是基于力导向的专用于带有 combo 的图的布局算法。通过自研改造经典力导向算法,将根据节点的 combo 信息,施加不同的力以达到同 combo 节点尽可能聚集,不同 combo 之间尽可能无重叠的布局。
|
||||
|
||||
## 使用指南
|
||||
|
||||
在有 Combo 的图上,推荐使用 `'comboCombined'` 或 `'comboForce'` 布局。其他内置布局将不会考虑 Combo 信息对布局的影响。
|
@ -1,4 +1,4 @@
|
||||
import { Graph, Utils } from '@antv/g6';
|
||||
import { Graph, treeToGraphData } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
@ -6,7 +6,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: Utils.treeToGraphData(data),
|
||||
data: treeToGraphData(data),
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
|
||||
node: {
|
||||
style: {
|
||||
@ -24,9 +24,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
layout: {
|
||||
type: 'compact-box',
|
@ -1,4 +1,4 @@
|
||||
import { Graph, Utils } from '@antv/g6';
|
||||
import { Graph, treeToGraphData } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
@ -6,7 +6,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: Utils.treeToGraphData(data),
|
||||
data: treeToGraphData(data),
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
|
||||
node: {
|
||||
style: {
|
||||
@ -27,9 +27,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
layout: {
|
||||
type: 'compact-box',
|
@ -5,7 +5,7 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicCompactBox.ts",
|
||||
"filename": "basic.js",
|
||||
"title": {
|
||||
"zh": "紧凑树",
|
||||
"en": "CompactBox Layout"
|
||||
@ -13,7 +13,7 @@
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-FgIT7w4OXwAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "topToBottomCompactBox.ts",
|
||||
"filename": "vertical.js",
|
||||
"title": {
|
||||
"zh": "从上向下布局",
|
||||
"en": "Top to Bottom CompactBox"
|
||||
@ -21,7 +21,7 @@
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*KrAqTrFbNjMAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "compactBoxLeftAlign.ts",
|
||||
"filename": "horizontal.js",
|
||||
"title": {
|
||||
"zh": "节点左对齐的紧凑树",
|
||||
"en": "CompactBox with Left Align Nodes"
|
@ -1,4 +1,4 @@
|
||||
import { Graph, Utils } from '@antv/g6';
|
||||
import { Graph, treeToGraphData } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
@ -6,7 +6,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: Utils.treeToGraphData(data),
|
||||
data: treeToGraphData(data),
|
||||
node: {
|
||||
style: {
|
||||
labelText: (data) => data.id,
|
||||
@ -28,9 +28,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-vertical',
|
||||
},
|
||||
type: 'cubic-vertical',
|
||||
},
|
||||
layout: {
|
||||
type: 'compact-box',
|
4
packages/site/examples/layout/compact-box/index.en.md
Normal file
4
packages/site/examples/layout/compact-box/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: CompactBox
|
||||
order: 3
|
||||
---
|
4
packages/site/examples/layout/compact-box/index.zh.md
Normal file
4
packages/site/examples/layout/compact-box/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: CompactBox 紧凑树
|
||||
order: 3
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/treeGraphLayout/compactBox.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/treeGraphLayout/compactBox.zh.md"></embed>
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: CompactBox
|
||||
order: 3
|
||||
---
|
||||
|
||||
The nodes with the same depth will be layed on the same level. The node size will be considred while doing layout. <br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' alt='compactbox' width='300'/>
|
||||
|
||||
## Usage
|
||||
|
||||
CompactBox is an appropriate layout method for tree data structure. As the demo below, you can deploy it in `layout` while instantiating Graph.
|
||||
|
||||
You can set different configurations for different nodes if the parameter is Function type. Please refer to the ducuments for more information.
|
@ -1,12 +0,0 @@
|
||||
---
|
||||
title: CompactBox 紧凑树
|
||||
order: 3
|
||||
---
|
||||
|
||||
从根节点开始,同一深度的节点在同一层,并且布局时会将节点大小考虑进去。 <br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*z-ESRoHTpvIAAAAAAAAAAABkARQnAQ' alt='compactbox' width='300'/>
|
||||
|
||||
## 使用指南
|
||||
|
||||
紧凑树适用于展示树结构数据,配合 TreeGraph 使用。如下面代码所示,可在实例化 TreeGraph 时使用该布局。
|
||||
|
||||
其配置项中 Function 类型的配置项可以为不同的元素配置不同的值。具体描述请查看相关教程。
|
@ -22,6 +22,7 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/8dacf27e-e1bc-4522-b6d3-4b6
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'line',
|
||||
style: {
|
||||
stroke: '#E2E2E2',
|
||||
},
|
@ -5,10 +5,10 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicConcentric.ts",
|
||||
"filename": "basic.js",
|
||||
"title": {
|
||||
"zh": "基本 Concentric 同心圆布局",
|
||||
"en": "Basic Concentric Layout"
|
||||
"zh": "Concentric 同心圆布局",
|
||||
"en": "Concentric Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*KXunQKOLCSAAAAAAAAAAAAAADmJ7AQ/original"
|
||||
}
|
4
packages/site/examples/layout/concentric/index.en.md
Normal file
4
packages/site/examples/layout/concentric/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Concentric Layout
|
||||
order: 10
|
||||
---
|
4
packages/site/examples/layout/concentric/index.zh.md
Normal file
4
packages/site/examples/layout/concentric/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Concentric 同心圆布局
|
||||
order: 10
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/concentric.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/concentric.zh.md"></embed>
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
title: Concentric Layout
|
||||
order: 10
|
||||
---
|
||||
|
||||
Concentric Layout places the nodes on concentric circles.
|
||||
|
||||
## Usage
|
||||
|
||||
As the demo below, you can deploy it in `layout` while instantiating Graph. it can also be used for [Subgraph Layout](/en/docs/manual/middle/layout/sub-layout). This algorithm will order the nodes according to the parameters first, then the node in the front of the order will be placed on the center of the concentric circles.
|
@ -1,10 +0,0 @@
|
||||
---
|
||||
title: Concentric 同心圆布局
|
||||
order: 10
|
||||
---
|
||||
|
||||
Concentric 同心圆布局将所有节点放置在同心圆上。
|
||||
|
||||
## 使用指南
|
||||
|
||||
G6 内置的 Concentric 同心圆布局可在实例化 Graph 时使用该布局。除此之外,还可以如[子图布局](/zh/docs/manual/middle/layout/sub-layout)所示单独使用布局。该算法首先根据参数指定的排序方式对节点进行排序。排序越靠前,节点将会被放置在越中心的位置。
|
85
packages/site/examples/layout/custom/demo/arc.js
Normal file
85
packages/site/examples/layout/custom/demo/arc.js
Normal file
@ -0,0 +1,85 @@
|
||||
import { BaseEdge, BaseLayout, ExtensionCategory, Graph, register } from '@antv/g6';
|
||||
|
||||
class ArcLayout extends BaseLayout {
|
||||
async execute(data, options) {
|
||||
const { nodeSep = 20, nodeSize } = { ...this.options, ...options };
|
||||
const { nodes } = data;
|
||||
return {
|
||||
nodes: nodes.map((node, index) => ({
|
||||
id: node.id,
|
||||
style: {
|
||||
x: index * (nodeSep + nodeSize),
|
||||
y: 0,
|
||||
},
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class ArcEdge extends BaseEdge {
|
||||
getKeyPath(attributes) {
|
||||
const [sourcePoint, targetPoint] = this.getEndpoints(attributes);
|
||||
const [sx, sy] = sourcePoint;
|
||||
const [tx] = targetPoint;
|
||||
const r = Math.abs(tx - sx) / 2;
|
||||
|
||||
return [
|
||||
['M', sx, sy],
|
||||
['A', r, r, 0, 0, sx < tx ? 1 : 0, tx, sy],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
register(ExtensionCategory.LAYOUT, 'arc', ArcLayout);
|
||||
register(ExtensionCategory.EDGE, 'arc', ArcEdge);
|
||||
|
||||
const palette = {
|
||||
analytics: 'rgb(158, 1, 66)',
|
||||
data: 'rgb(213, 62, 79)',
|
||||
animate: 'rgb(244, 109, 67)',
|
||||
display: 'rgb(253, 174, 97)',
|
||||
flex: 'rgb(254, 224, 139)',
|
||||
physics: 'rgb(230, 245, 152)',
|
||||
query: 'rgb(171, 221, 164)',
|
||||
scale: 'rgb(102, 194, 165)',
|
||||
util: 'rgb(50, 136, 189)',
|
||||
vis: 'rgb(94, 79, 162)',
|
||||
};
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/70cde3be-22e8-4291-98f1-4d5a5b75b62f.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const getCluster = (id) => data.nodes.find((node) => node.id === id).cluster;
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
autoFit: 'view',
|
||||
animation: false,
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
fill: (d) => palette[d.cluster],
|
||||
ports: [{ position: 'top' }],
|
||||
labelText: (d) => d.name,
|
||||
labelTextAlign: 'start',
|
||||
labelTextBaseline: 'middle',
|
||||
labelTransform: 'rotate(90)',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'arc',
|
||||
style: {
|
||||
stroke: (d) => `linear-gradient(${palette[getCluster(d.source)]}, ${palette[getCluster(d.source)]})`,
|
||||
strokeOpacity: 0.5,
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'arc',
|
||||
nodeSize: 20,
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
93
packages/site/examples/layout/custom/demo/bi-graph.js
Normal file
93
packages/site/examples/layout/custom/demo/bi-graph.js
Normal file
@ -0,0 +1,93 @@
|
||||
import { BaseLayout, ExtensionCategory, Graph, register } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{ id: '0', data: { cluster: 'A' } },
|
||||
{ id: '1', data: { cluster: 'A' } },
|
||||
{ id: '2', data: { cluster: 'A' } },
|
||||
{ id: '3', data: { cluster: 'A' } },
|
||||
{ id: '4', data: { cluster: 'A' } },
|
||||
{ id: '5', data: { cluster: 'A' } },
|
||||
{ id: '6', data: { cluster: 'B' } },
|
||||
{ id: '7', data: { cluster: 'B' } },
|
||||
{ id: '8', data: { cluster: 'B' } },
|
||||
{ id: '9', data: { cluster: 'B' } },
|
||||
],
|
||||
edges: [
|
||||
{ source: '0', target: '6' },
|
||||
{ source: '0', target: '7' },
|
||||
{ source: '0', target: '9' },
|
||||
{ source: '1', target: '6' },
|
||||
{ source: '1', target: '9' },
|
||||
{ source: '1', target: '7' },
|
||||
{ source: '2', target: '8' },
|
||||
{ source: '2', target: '9' },
|
||||
{ source: '2', target: '6' },
|
||||
{ source: '3', target: '8' },
|
||||
{ source: '4', target: '6' },
|
||||
{ source: '4', target: '7' },
|
||||
{ source: '5', target: '9' },
|
||||
],
|
||||
};
|
||||
|
||||
class BiLayout extends BaseLayout {
|
||||
id = 'bi-layout';
|
||||
|
||||
async execute(data, options) {
|
||||
const { sep = 100, nodeSep = 20, nodeSize = 32 } = { ...this.options, ...options };
|
||||
|
||||
const [A, B] = data.nodes.reduce(
|
||||
(acc, curr) => {
|
||||
acc[curr.data.cluster === 'A' ? 0 : 1].push(curr);
|
||||
return acc;
|
||||
},
|
||||
[[], []],
|
||||
);
|
||||
|
||||
return {
|
||||
nodes: [
|
||||
...A.map((node, i) => ({
|
||||
id: node.id,
|
||||
style: {
|
||||
x: i * (nodeSep + nodeSize),
|
||||
y: 0,
|
||||
},
|
||||
})),
|
||||
...B.map((node, i) => ({
|
||||
id: node.id,
|
||||
style: {
|
||||
x: i * (nodeSep + nodeSize),
|
||||
y: sep,
|
||||
},
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
register(ExtensionCategory.LAYOUT, 'bi', BiLayout);
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
animation: false,
|
||||
autoFit: 'center',
|
||||
node: {
|
||||
style: {
|
||||
labelText: (d) => d.id,
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'bi',
|
||||
biSep: 300,
|
||||
nodeSep: 20,
|
||||
nodeSize: 32,
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element', 'zoom-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
24
packages/site/examples/layout/custom/demo/meta.json
Normal file
24
packages/site/examples/layout/custom/demo/meta.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": {
|
||||
"zh": "中文分类",
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "bi-graph.js",
|
||||
"title": {
|
||||
"zh": "二分图布局",
|
||||
"en": "Bi-graph Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*G4-YT4NDA2oAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "arc.js",
|
||||
"title": {
|
||||
"zh": "弧线图",
|
||||
"en": "Arc Diagram"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*_eivQrJXt8sAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
]
|
||||
}
|
4
packages/site/examples/layout/custom/index.en.md
Normal file
4
packages/site/examples/layout/custom/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Custom Layout
|
||||
order: 16
|
||||
---
|
4
packages/site/examples/layout/custom/index.zh.md
Normal file
4
packages/site/examples/layout/custom/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: 自定义布局
|
||||
order: 16
|
||||
---
|
@ -6,44 +6,44 @@ fetch('https://assets.antv.antgroup.com/g6/dagre-combo.json')
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
animation: true,
|
||||
data,
|
||||
node: {
|
||||
type: 'rect',
|
||||
style: {
|
||||
size: [60, 30],
|
||||
radius: 8,
|
||||
labelText: (d) => d.id,
|
||||
labelPlacement: 'center',
|
||||
ports: [{ placement: 'top' }, { placement: 'bottom' }],
|
||||
},
|
||||
palette: {
|
||||
field: (d) => d.combo,
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'cubic-vertical',
|
||||
style: {
|
||||
endArrow: true,
|
||||
},
|
||||
},
|
||||
combo: {
|
||||
type: 'rect',
|
||||
style: {
|
||||
radius: 8,
|
||||
labelText: (d) => d.id,
|
||||
lineDash: 0,
|
||||
collapsedLineDash: [5, 5],
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'antv-dagre',
|
||||
ranksep: 50,
|
||||
nodesep: 5,
|
||||
sortByCombo: true,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
type: 'rect',
|
||||
size: [60, 30],
|
||||
radius: 8,
|
||||
labelPlacement: 'center',
|
||||
labelText: (d) => d.id,
|
||||
ports: [{ placement: 'top' }, { placement: 'bottom' }],
|
||||
fill: (d) => {
|
||||
const styles = { A: '#F09056', B: '#D580FF', C: '#01C9C9' };
|
||||
return styles[d.style.parentId] || '#1883FF';
|
||||
},
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-vertical',
|
||||
endArrow: true,
|
||||
lineWidth: 2,
|
||||
stroke: '#C2C8D5',
|
||||
},
|
||||
},
|
||||
combo: {
|
||||
style: {
|
||||
type: 'rect',
|
||||
labelText: (d) => d.id,
|
||||
lineDash: 0,
|
||||
collapsedLineDash: [5, 5],
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-element', 'drag-canvas', 'zoom-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -29,18 +29,18 @@ const data = {
|
||||
],
|
||||
};
|
||||
|
||||
const layouts = {
|
||||
Default: { type: 'antv-dagre', nodesep: 100, ranksep: 70, controlPoints: true },
|
||||
LR: { type: 'antv-dagre', rankdir: 'LR', align: 'DL', nodesep: 50, ranksep: 70, controlPoints: true },
|
||||
'LR&UL': { type: 'antv-dagre', rankdir: 'LR', align: 'UL', controlPoints: true, nodesep: 50, ranksep: 70 },
|
||||
};
|
||||
|
||||
const container = document.getElementById('container');
|
||||
|
||||
const graph = new Graph({
|
||||
container,
|
||||
animation: false,
|
||||
data,
|
||||
layout: layouts.Default,
|
||||
layout: {
|
||||
type: 'antv-dagre',
|
||||
nodesep: 100,
|
||||
ranksep: 70,
|
||||
controlPoints: true,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
type: 'rect',
|
||||
@ -51,8 +51,8 @@ const graph = new Graph({
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'polyline',
|
||||
style: {
|
||||
type: 'polyline',
|
||||
endArrow: true,
|
||||
lineWidth: 2,
|
||||
stroke: '#C2C8D5',
|
||||
@ -64,23 +64,17 @@ const graph = new Graph({
|
||||
|
||||
graph.render();
|
||||
|
||||
const btnContainer = document.createElement('div');
|
||||
btnContainer.style.position = 'absolute';
|
||||
btnContainer.style.zIndex = '10';
|
||||
container.appendChild(btnContainer);
|
||||
const tip = document.createElement('span');
|
||||
tip.innerHTML = '👉 Change configs:';
|
||||
btnContainer.appendChild(tip);
|
||||
window.addPanel((gui) => {
|
||||
const config = { layout: 'default' };
|
||||
const layouts = {
|
||||
default: { type: 'antv-dagre', nodesep: 100, ranksep: 70, controlPoints: true },
|
||||
LR: { type: 'antv-dagre', rankdir: 'LR', align: 'DL', nodesep: 50, ranksep: 70, controlPoints: true },
|
||||
'LR&UL': { type: 'antv-dagre', rankdir: 'LR', align: 'UL', controlPoints: true, nodesep: 50, ranksep: 70 },
|
||||
};
|
||||
|
||||
Object.keys(layouts).forEach((name, i) => {
|
||||
const btn = document.createElement('a');
|
||||
btn.innerHTML = name;
|
||||
btn.style.backgroundColor = 'rgba(255, 255, 255, 0.8)';
|
||||
btn.style.padding = '4px';
|
||||
btn.style.marginLeft = i > 0 ? '24px' : '8px';
|
||||
btnContainer.appendChild(btn);
|
||||
btn.addEventListener('click', () => {
|
||||
graph.setLayout(layouts[name]);
|
||||
graph.layout();
|
||||
gui.add(config, 'layout', Object.keys(layouts)).onChange(async (layout) => {
|
||||
graph.setLayout(layouts[layout]);
|
||||
await graph.layout();
|
||||
graph.fitCenter();
|
||||
});
|
||||
});
|
@ -20,8 +20,8 @@ const graph = new Graph({
|
||||
],
|
||||
},
|
||||
node: {
|
||||
type: 'rect',
|
||||
style: {
|
||||
type: 'rect',
|
||||
radius: 10,
|
||||
iconText: (d) => d.data.label,
|
||||
size: (d) => [d.data.width, d.data.height],
|
||||
@ -32,8 +32,8 @@ const graph = new Graph({
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'polyline',
|
||||
style: {
|
||||
type: 'polyline',
|
||||
router: true,
|
||||
},
|
||||
},
|
@ -5,7 +5,7 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "antv-dagre.ts",
|
||||
"filename": "antv-dagre.js",
|
||||
"title": {
|
||||
"zh": "Dagre 流程图",
|
||||
"en": "Dagre Layout"
|
||||
@ -13,7 +13,7 @@
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ESU8SrsUnlwAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "antv-dagre-combo.ts",
|
||||
"filename": "antv-dagre-combo.js",
|
||||
"title": {
|
||||
"zh": "带有 Combo 的流程图",
|
||||
"en": "Dagre with Combos"
|
||||
@ -21,7 +21,7 @@
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*h60aQKusJRcAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "dagre.ts",
|
||||
"filename": "dagre.js",
|
||||
"title": {
|
||||
"zh": "Dagre.js 布局",
|
||||
"en": "Dagre.js Layout"
|
4
packages/site/examples/layout/dagre/index.en.md
Normal file
4
packages/site/examples/layout/dagre/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Dagre Layout
|
||||
order: 1
|
||||
---
|
4
packages/site/examples/layout/dagre/index.zh.md
Normal file
4
packages/site/examples/layout/dagre/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Dagre 布局
|
||||
order: 1
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/dagre.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/dagre.zh.md"></embed>
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
title: Dagre Layout
|
||||
order: 1
|
||||
---
|
||||
|
||||
Dagre Layout is an appropriate layout method for directed flow graph. It will calculate the levels and positions of nodes automatically according to the edge directions in the data.
|
||||
|
||||
## Usage
|
||||
|
||||
As the demo below, you can deploy it in `layout` while instantiating Graph. it can also be used for [Subgraph Layout](/en/docs/manual/middle/layout/sub-layout). By tuning the parameters, you can adjust the layout direction, node alignment, node separation, level separation, and so on.
|
||||
|
||||
- Example 1 : Simple dagre layout.
|
||||
- Example 2 : Dagre Layout with combos.
|
||||
- Example 3 : Dagre layout from left to right and align top.
|
||||
- Example 4 : Dagre layout from left to right.
|
||||
- Example 5 : Translate the layout parameters in dynamic.
|
@ -1,16 +0,0 @@
|
||||
---
|
||||
title: Dagre 流程图布局
|
||||
order: 1
|
||||
---
|
||||
|
||||
Dagre 是适合有向流程图的布局算法。其根据图数据中边的方向,自动计算节点的层级及位置。
|
||||
|
||||
## 使用指南
|
||||
|
||||
G6 内置的 Dagre 布局可以实现有向图的自动分层布局。如下面代码所示,可在实例化 Graph 时使用该布局。除此之外,还可以如[子图布局](/zh/docs/manual/middle/layout/sub-layout)所示单独使用布局。该布局可以通过配置调整布局方向、节点对齐方式、节点间距、层高等。
|
||||
|
||||
- 代码演示 1 :简单的 Dagre 布局。
|
||||
- 代码演示 2 :带有 Combo 的 Dagre 布局(目前只能处理好同层节点的 Combo 问题)。
|
||||
- 代码演示 3 :自左向右向上对齐的 Dagre 布局。
|
||||
- 代码演示 4 :自左向右的 Dagre 布局。
|
||||
- 代码演示 5 :Dagre 布局参数动态变化。
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/treeGraphLayout/dendrogram.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/treeGraphLayout/dendrogram.zh.md"></embed>
|
@ -1,4 +1,4 @@
|
||||
import { Graph, Utils } from '@antv/g6';
|
||||
import { Graph, treeToGraphData } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
@ -6,26 +6,16 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: Utils.treeToGraphData(data),
|
||||
data: treeToGraphData(data),
|
||||
node: {
|
||||
style: {
|
||||
labelText: (d) => d.id,
|
||||
labelPlacement: (model) => (model.style!.children?.length ? 'left' : 'right'),
|
||||
ports: [
|
||||
{
|
||||
placement: 'right',
|
||||
},
|
||||
{
|
||||
placement: 'left',
|
||||
},
|
||||
],
|
||||
labelPlacement: (model) => (model.children?.length ? 'left' : 'right'),
|
||||
ports: [{ placement: 'right' }, { placement: 'left' }],
|
||||
},
|
||||
},
|
||||
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
type: 'cubic-horizontal',
|
||||
},
|
||||
layout: {
|
||||
type: 'dendrogram',
|
||||
@ -33,7 +23,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.j
|
||||
nodeSep: 36,
|
||||
rankSep: 250,
|
||||
},
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand-tree'],
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -5,18 +5,18 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicDendrogram.ts",
|
||||
"filename": "basic.js",
|
||||
"title": {
|
||||
"zh": "生态树",
|
||||
"en": "Basic Dendrogram Layout"
|
||||
"en": "Dendrogram Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*P-qOSoDNuckAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "tbDendrogram.ts",
|
||||
"filename": "vertical.js",
|
||||
"title": {
|
||||
"zh": "至上而下的生态树",
|
||||
"en": "Top to Bottom Dendrogram"
|
||||
"zh": "垂直布局",
|
||||
"en": "Vertical Layout"
|
||||
},
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*nTKmRKkyUVUAAAAAAAAAAABkARQnAQ"
|
||||
}
|
||||
|
@ -1,46 +0,0 @@
|
||||
import { Graph, Utils } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: Utils.treeToGraphData(data),
|
||||
node: {
|
||||
style: (model) => {
|
||||
const hasChildren = !!model.style!.children?.length;
|
||||
return {
|
||||
labelText: model.id,
|
||||
labelPlacement: hasChildren ? 'right' : 'bottom',
|
||||
labelMaxWidth: 200,
|
||||
labelTextAlign: 'start',
|
||||
transform: hasChildren ? '' : 'rotate(90deg)',
|
||||
ports: [
|
||||
{
|
||||
placement: 'bottom',
|
||||
},
|
||||
{
|
||||
placement: 'top',
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
edge: {
|
||||
style: {
|
||||
type: 'cubic-vertical',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'dendrogram',
|
||||
direction: 'TB', // H / V / LR / RL / TB / BT
|
||||
nodeSep: 40,
|
||||
rankSep: 100,
|
||||
},
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand-tree'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
38
packages/site/examples/layout/dendrogram/demo/vertical.js
Normal file
38
packages/site/examples/layout/dendrogram/demo/vertical.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { Graph, treeToGraphData } from '@antv/g6';
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/algorithm-category.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
autoFit: 'view',
|
||||
data: treeToGraphData(data),
|
||||
node: {
|
||||
style: (data) => {
|
||||
const isLeaf = !data.children?.length;
|
||||
return {
|
||||
labelText: data.id,
|
||||
labelWordWrap: true,
|
||||
labelWordWrapWidth: 150,
|
||||
labelDy: isLeaf ? 0 : 20,
|
||||
labelTextAlign: isLeaf ? 'start' : 'center',
|
||||
labelTextBaseline: 'middle',
|
||||
labelTransform: isLeaf ? 'rotate(90deg)' : '',
|
||||
ports: [{ placement: 'bottom' }, { placement: 'top' }],
|
||||
};
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'cubic-vertical',
|
||||
},
|
||||
layout: {
|
||||
type: 'dendrogram',
|
||||
direction: 'TB', // H / V / LR / RL / TB / BT
|
||||
nodeSep: 40,
|
||||
rankSep: 100,
|
||||
},
|
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element', 'collapse-expand-tree'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -2,11 +2,3 @@
|
||||
title: Dendrogram
|
||||
order: 4
|
||||
---
|
||||
|
||||
The leaves will be aligned on the same level. This algorithm does not consider the node size, which means all the nodes will be regarded as unit size with 1px. <br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' alt='dendrogram' width='300'/>
|
||||
|
||||
## Usage
|
||||
|
||||
Dendrogram is an appropriate layout method for tree data structure. Please use it with TreeGraph. As the demo below, you can deploy it in `layout` while instantiating Graph.
|
||||
|
||||
You can set different configurations for different nodes if the parameter is Function type. Please refer to the ducuments for more information.
|
||||
|
@ -2,9 +2,3 @@
|
||||
title: Dendrogram 生态树
|
||||
order: 4
|
||||
---
|
||||
|
||||
不管数据的深度多少,总是叶节点对齐。不考虑节点大小,布局时将节点视为 1 个像素点。 <br /> <img src='https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*zX7tSLqBvwcAAAAAAAAAAABkARQnAQ' alt='dendrogram' width='300'/>
|
||||
|
||||
## 使用指南
|
||||
|
||||
生态树适用于展示树结构数据,配合 TreeGraph 使用。如下面代码所示,可在实例化 TreeGraph 时使用该布局。
|
||||
|
@ -0,0 +1,56 @@
|
||||
import { CameraSetting, ExtensionCategory, Graph, register } from '@antv/g6';
|
||||
import { Light, Line3D, ObserveCanvas3D, Sphere, ZoomCanvas3D, renderer } from '@antv/g6-extension-3d';
|
||||
|
||||
register(ExtensionCategory.PLUGIN, '3d-light', Light);
|
||||
register(ExtensionCategory.NODE, 'sphere', Sphere);
|
||||
register(ExtensionCategory.EDGE, 'line3d', Line3D);
|
||||
register(ExtensionCategory.PLUGIN, 'camera-setting', CameraSetting);
|
||||
register(ExtensionCategory.BEHAVIOR, 'zoom-canvas-3d', ZoomCanvas3D);
|
||||
register(ExtensionCategory.BEHAVIOR, 'observe-canvas-3d', ObserveCanvas3D);
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/d3-force-3d.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
animation: true,
|
||||
renderer,
|
||||
data,
|
||||
layout: {
|
||||
type: 'd3-force-3d',
|
||||
},
|
||||
node: {
|
||||
type: 'sphere',
|
||||
style: {
|
||||
materialType: 'phong',
|
||||
},
|
||||
palette: {
|
||||
color: 'tableau',
|
||||
type: 'group',
|
||||
field: 'group',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
type: 'line3d',
|
||||
},
|
||||
behaviors: ['observe-canvas-3d', 'zoom-canvas-3d'],
|
||||
plugins: [
|
||||
{
|
||||
type: 'camera-setting',
|
||||
projectionMode: 'perspective',
|
||||
near: 0.1,
|
||||
far: 1000,
|
||||
fov: 45,
|
||||
aspect: 1,
|
||||
},
|
||||
{
|
||||
type: '3d-light',
|
||||
directional: {
|
||||
direction: [0, 0, 1],
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -6,6 +6,7 @@ fetch('https://gw.alipayobjects.com/os/antvdemo/assets/data/relations.json')
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
autoFit: 'view',
|
||||
layout: {
|
||||
type: 'force-atlas2',
|
||||
preventOverlap: true,
|
@ -0,0 +1,87 @@
|
||||
import { BaseBehavior, ExtensionCategory, Graph, invokeLayoutMethod, register } from '@antv/g6';
|
||||
|
||||
function getData(width, size = 200) {
|
||||
const k = width / 200;
|
||||
const r = randomUniform(k * 2, k * 8);
|
||||
const n = 4;
|
||||
return {
|
||||
nodes: Array.from({ length: size }, (_, i) => ({ id: `${i}`, data: { r: r(), group: i && (i % n) + 1 } })),
|
||||
edges: [],
|
||||
};
|
||||
}
|
||||
|
||||
function randomUniform(min, max) {
|
||||
min = min == null ? 0 : +min;
|
||||
max = max == null ? 1 : +max;
|
||||
if (arguments.length === 1) (max = min), (min = 0);
|
||||
else max -= min;
|
||||
return function () {
|
||||
return Math.random() * max + min;
|
||||
};
|
||||
}
|
||||
|
||||
class CollisionElement extends BaseBehavior {
|
||||
constructor(context) {
|
||||
super(context, {});
|
||||
this.onPointerMove = this.onPointerMove.bind(this);
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.context.graph.on('pointermove', this.onPointerMove);
|
||||
}
|
||||
|
||||
onPointerMove(event) {
|
||||
const pos = this.context.graph.getCanvasByClient([event.client.x, event.client.y]);
|
||||
const layoutInstance = this.context.layout
|
||||
?.getLayoutInstance()
|
||||
.find((layout) => ['d3-force', 'd3-force-3d'].includes(layout?.id));
|
||||
|
||||
if (layoutInstance) {
|
||||
invokeLayoutMethod(layoutInstance, 'setFixedPosition', '0', [...pos]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register(ExtensionCategory.BEHAVIOR, 'collision-element', CollisionElement);
|
||||
|
||||
const container = document.getElementById('container');
|
||||
const width = container.scrollWidth;
|
||||
|
||||
const graph = new Graph({
|
||||
container,
|
||||
animation: true,
|
||||
data: getData(width),
|
||||
layout: {
|
||||
type: 'd3force',
|
||||
alphaTarget: 0.3,
|
||||
velocityDecay: 0.1,
|
||||
x: {
|
||||
strength: 0.01,
|
||||
},
|
||||
y: {
|
||||
strength: 0.01,
|
||||
},
|
||||
collide: {
|
||||
radius: (d) => d.data.r,
|
||||
iterations: 3,
|
||||
},
|
||||
manyBody: {
|
||||
strength: (d, i) => (i ? 0 : (-width * 2) / 3),
|
||||
},
|
||||
link: false,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: (d) => (d.id === '0' ? 0 : d.data.r * 2),
|
||||
},
|
||||
palette: {
|
||||
color: 'tableau',
|
||||
type: 'group',
|
||||
field: (d) => d.data.group,
|
||||
},
|
||||
},
|
||||
behaviors: ['collision-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
30
packages/site/examples/layout/force-directed/demo/d3-force.js
vendored
Normal file
30
packages/site/examples/layout/force-directed/demo/d3-force.js
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cluster.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
animation: true,
|
||||
data,
|
||||
node: {
|
||||
style: {
|
||||
labelText: (d) => d.id,
|
||||
ports: [],
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'd3force',
|
||||
collide: {
|
||||
strength: 0.5,
|
||||
},
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
31
packages/site/examples/layout/force-directed/demo/force.js
Normal file
31
packages/site/examples/layout/force-directed/demo/force.js
Normal file
@ -0,0 +1,31 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cluster.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
node: {
|
||||
style: {
|
||||
labelText: (d) => d.id,
|
||||
ports: [],
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'force',
|
||||
linkDistance: 50,
|
||||
animation: true,
|
||||
clustering: true,
|
||||
nodeClusterBy: 'cluster',
|
||||
clusterNodeStrength: 70,
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
47
packages/site/examples/layout/force-directed/demo/mesh.js
Normal file
47
packages/site/examples/layout/force-directed/demo/mesh.js
Normal file
@ -0,0 +1,47 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
function getData(size = 10) {
|
||||
const nodes = Array.from({ length: size * size }, (_, i) => ({ id: `${i}` }));
|
||||
const edges = [];
|
||||
for (let y = 0; y < size; ++y) {
|
||||
for (let x = 0; x < size; ++x) {
|
||||
if (y > 0) edges.push({ source: `${(y - 1) * size + x}`, target: `${y * size + x}` });
|
||||
if (x > 0) edges.push({ source: `${y * size + (x - 1)}`, target: `${y * size + x}` });
|
||||
}
|
||||
}
|
||||
return { nodes, edges };
|
||||
}
|
||||
|
||||
const graph = new Graph({
|
||||
animation: true,
|
||||
data: getData(),
|
||||
layout: {
|
||||
type: 'd3force',
|
||||
manyBody: {
|
||||
strength: -30,
|
||||
},
|
||||
link: {
|
||||
strength: 1,
|
||||
distance: 20,
|
||||
iterations: 10,
|
||||
},
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 10,
|
||||
fill: '#000',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
stroke: '#000',
|
||||
},
|
||||
},
|
||||
behaviors: [{ type: 'drag-element-force' }, 'zoom-canvas'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
|
||||
window.addPanel((gui) => {
|
||||
gui.add({ msg: 'Try to drag nodes' }, 'msg').name('Tips').disable();
|
||||
});
|
56
packages/site/examples/layout/force-directed/demo/meta.json
Normal file
56
packages/site/examples/layout/force-directed/demo/meta.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"title": {
|
||||
"zh": "中文分类",
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "force.js",
|
||||
"title": {
|
||||
"zh": "Force 聚类",
|
||||
"en": "Clustering Force Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sA14SZo9BBMAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "atlas2.js",
|
||||
"title": {
|
||||
"zh": "Force Atlas 2",
|
||||
"en": "Force-Atlas 2 Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-HgiS6CyuuEAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "d3-force.js",
|
||||
"title": {
|
||||
"zh": "D3 力导向布局",
|
||||
"en": "D3 Force Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-_sFS5IRGGcAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "3d-force.js",
|
||||
"title": {
|
||||
"zh": "3D 力导向布局",
|
||||
"en": "3D Force Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*4mbSTJLOXkgAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "mesh.js",
|
||||
"title": {
|
||||
"zh": "网格效果",
|
||||
"en": "Mesh Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ykD5QqSEgeEAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "collision.js",
|
||||
"title": {
|
||||
"zh": "弹性碰撞效果",
|
||||
"en": "Collision Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*yzv_To2Wm_EAAAAAAAAAAAAADmJ7AQ/original"
|
||||
}
|
||||
]
|
||||
}
|
4
packages/site/examples/layout/force-directed/index.en.md
Normal file
4
packages/site/examples/layout/force-directed/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Force-directed Layout
|
||||
order: 0
|
||||
---
|
4
packages/site/examples/layout/force-directed/index.zh.md
Normal file
4
packages/site/examples/layout/force-directed/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: 力导向图布局
|
||||
order: 0
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/force.en.md"></embed>
|
@ -1,11 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
# Force Layout
|
||||
|
||||
<embed src="@/docs/api/graphLayout/force.zh.md"></embed>
|
||||
|
||||
# Force Atlas 2 Layout
|
||||
|
||||
<embed src="@/docs/api/graphLayout/forceAtlas2.zh.md"></embed>
|
@ -1,546 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
data: {
|
||||
cluster: 'a',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
data: {
|
||||
cluster: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
data: {
|
||||
cluster: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
data: {
|
||||
cluster: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
data: {
|
||||
cluster: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
data: {
|
||||
cluster: 'b',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
data: {
|
||||
cluster: 'c',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
data: {
|
||||
cluster: 'd',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
data: {
|
||||
cluster: 'd',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
data: {
|
||||
cluster: 'd',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
id: 'edge-583',
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
id: 'edge-0',
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
id: 'edge-888',
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-560',
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
id: 'edge-34',
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-654',
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
id: 'edge-317',
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
id: 'edge-962',
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
id: 'edge-746',
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-75',
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
id: 'edge-80',
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-674',
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-795',
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
id: 'edge-886',
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
id: 'edge-630',
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-710',
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-284',
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-758',
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-288',
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-103',
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-873',
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-108',
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-214',
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-928',
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
id: 'edge-717',
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-752',
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-424',
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-755',
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-822',
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-366',
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-411',
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-781',
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
id: 'edge-742',
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-762',
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-519',
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-187',
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-919',
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-854',
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
id: 'edge-199',
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-475',
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-55',
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-528',
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-741',
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-920',
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-457',
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-524',
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
id: 'edge-814',
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
id: 'edge-258',
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-222',
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-803',
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-693',
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-491',
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
id: 'edge-46',
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-145',
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-45',
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
id: 'edge-98',
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
id: 'edge-993',
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-514',
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-361',
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-154',
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
data.nodes.forEach((node) => (node.data.size = Math.random() * 30 + 5));
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
node: {
|
||||
style: {
|
||||
type: 'circle',
|
||||
size: (d) => d.data.size,
|
||||
labelText: (d) => d.id,
|
||||
ports: [],
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
color: 'antv',
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'force',
|
||||
linkDistance: 50,
|
||||
animation: true,
|
||||
clustering: true,
|
||||
nodeClusterBy: 'cluster',
|
||||
clusterNodeStrength: 70,
|
||||
},
|
||||
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
zoomRange: [0.1, 5],
|
||||
autoResize: true,
|
||||
});
|
||||
|
||||
graph.render();
|
@ -1,551 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{
|
||||
id: '0',
|
||||
data: {
|
||||
label: '0',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '1',
|
||||
data: {
|
||||
label: '1',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
data: {
|
||||
label: '2',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
data: {
|
||||
label: '3',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
data: {
|
||||
label: '4',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
data: {
|
||||
label: '5',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '6',
|
||||
data: {
|
||||
label: '6',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '7',
|
||||
data: {
|
||||
label: '7',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '8',
|
||||
data: {
|
||||
label: '8',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '9',
|
||||
data: {
|
||||
label: '9',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '10',
|
||||
data: {
|
||||
label: '10',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '11',
|
||||
data: {
|
||||
label: '11',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '12',
|
||||
data: {
|
||||
label: '12',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '13',
|
||||
data: {
|
||||
label: '13',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '14',
|
||||
data: {
|
||||
label: '14',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '15',
|
||||
data: {
|
||||
label: '15',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '16',
|
||||
data: {
|
||||
label: '16',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '17',
|
||||
data: {
|
||||
label: '17',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '18',
|
||||
data: {
|
||||
label: '18',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '19',
|
||||
data: {
|
||||
label: '19',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '20',
|
||||
data: {
|
||||
label: '20',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '21',
|
||||
data: {
|
||||
label: '21',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '22',
|
||||
data: {
|
||||
label: '22',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '23',
|
||||
data: {
|
||||
label: '23',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '24',
|
||||
data: {
|
||||
label: '24',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '25',
|
||||
data: {
|
||||
label: '25',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '26',
|
||||
data: {
|
||||
label: '26',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '27',
|
||||
data: {
|
||||
label: '27',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '28',
|
||||
data: {
|
||||
label: '28',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '29',
|
||||
data: {
|
||||
label: '29',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '30',
|
||||
data: {
|
||||
label: '30',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '31',
|
||||
data: {
|
||||
label: '31',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '32',
|
||||
data: {
|
||||
label: '32',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '33',
|
||||
data: {
|
||||
label: '33',
|
||||
},
|
||||
},
|
||||
],
|
||||
edges: [
|
||||
{
|
||||
id: 'edge-442',
|
||||
source: '0',
|
||||
target: '1',
|
||||
},
|
||||
{
|
||||
id: 'edge-825',
|
||||
source: '0',
|
||||
target: '2',
|
||||
},
|
||||
{
|
||||
id: 'edge-100',
|
||||
source: '0',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-378',
|
||||
source: '0',
|
||||
target: '4',
|
||||
},
|
||||
{
|
||||
id: 'edge-691',
|
||||
source: '0',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-983',
|
||||
source: '0',
|
||||
target: '7',
|
||||
},
|
||||
{
|
||||
id: 'edge-491',
|
||||
source: '0',
|
||||
target: '8',
|
||||
},
|
||||
{
|
||||
id: 'edge-38',
|
||||
source: '0',
|
||||
target: '9',
|
||||
},
|
||||
{
|
||||
id: 'edge-547',
|
||||
source: '0',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-126',
|
||||
source: '0',
|
||||
target: '11',
|
||||
},
|
||||
{
|
||||
id: 'edge-905',
|
||||
source: '0',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-931',
|
||||
source: '0',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-329',
|
||||
source: '0',
|
||||
target: '15',
|
||||
},
|
||||
{
|
||||
id: 'edge-798',
|
||||
source: '0',
|
||||
target: '16',
|
||||
},
|
||||
{
|
||||
id: 'edge-130',
|
||||
source: '2',
|
||||
target: '3',
|
||||
},
|
||||
{
|
||||
id: 'edge-132',
|
||||
source: '4',
|
||||
target: '5',
|
||||
},
|
||||
{
|
||||
id: 'edge-587',
|
||||
source: '4',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-772',
|
||||
source: '5',
|
||||
target: '6',
|
||||
},
|
||||
{
|
||||
id: 'edge-582',
|
||||
source: '7',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-922',
|
||||
source: '8',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-559',
|
||||
source: '9',
|
||||
target: '10',
|
||||
},
|
||||
{
|
||||
id: 'edge-915',
|
||||
source: '10',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-304',
|
||||
source: '10',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-88',
|
||||
source: '10',
|
||||
target: '12',
|
||||
},
|
||||
{
|
||||
id: 'edge-343',
|
||||
source: '10',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-692',
|
||||
source: '10',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-29',
|
||||
source: '10',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-390',
|
||||
source: '11',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-46',
|
||||
source: '11',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-170',
|
||||
source: '11',
|
||||
target: '14',
|
||||
},
|
||||
{
|
||||
id: 'edge-51',
|
||||
source: '12',
|
||||
target: '13',
|
||||
},
|
||||
{
|
||||
id: 'edge-387',
|
||||
source: '16',
|
||||
target: '17',
|
||||
},
|
||||
{
|
||||
id: 'edge-598',
|
||||
source: '16',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-894',
|
||||
source: '16',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-448',
|
||||
source: '16',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-921',
|
||||
source: '17',
|
||||
target: '18',
|
||||
},
|
||||
{
|
||||
id: 'edge-374',
|
||||
source: '17',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-11',
|
||||
source: '18',
|
||||
target: '19',
|
||||
},
|
||||
{
|
||||
id: 'edge-899',
|
||||
source: '19',
|
||||
target: '20',
|
||||
},
|
||||
{
|
||||
id: 'edge-790',
|
||||
source: '19',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-294',
|
||||
source: '19',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-353',
|
||||
source: '19',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-546',
|
||||
source: '20',
|
||||
target: '21',
|
||||
},
|
||||
{
|
||||
id: 'edge-105',
|
||||
source: '21',
|
||||
target: '22',
|
||||
},
|
||||
{
|
||||
id: 'edge-261',
|
||||
source: '22',
|
||||
target: '24',
|
||||
},
|
||||
{
|
||||
id: 'edge-393',
|
||||
source: '22',
|
||||
target: '25',
|
||||
},
|
||||
{
|
||||
id: 'edge-779',
|
||||
source: '22',
|
||||
target: '26',
|
||||
},
|
||||
{
|
||||
id: 'edge-149',
|
||||
source: '22',
|
||||
target: '23',
|
||||
},
|
||||
{
|
||||
id: 'edge-313',
|
||||
source: '22',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-805',
|
||||
source: '22',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-538',
|
||||
source: '22',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-884',
|
||||
source: '22',
|
||||
target: '32',
|
||||
},
|
||||
{
|
||||
id: 'edge-824',
|
||||
source: '22',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-519',
|
||||
source: '23',
|
||||
target: '28',
|
||||
},
|
||||
{
|
||||
id: 'edge-496',
|
||||
source: '23',
|
||||
target: '27',
|
||||
},
|
||||
{
|
||||
id: 'edge-402',
|
||||
source: '23',
|
||||
target: '29',
|
||||
},
|
||||
{
|
||||
id: 'edge-736',
|
||||
source: '23',
|
||||
target: '30',
|
||||
},
|
||||
{
|
||||
id: 'edge-782',
|
||||
source: '23',
|
||||
target: '31',
|
||||
},
|
||||
{
|
||||
id: 'edge-87',
|
||||
source: '23',
|
||||
target: '33',
|
||||
},
|
||||
{
|
||||
id: 'edge-27',
|
||||
source: '32',
|
||||
target: '33',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const container = document.getElementById('container');
|
||||
const descriptionDiv = document.createElement('div');
|
||||
descriptionDiv.innerHTML = 'Force layout, linkDistance = 50, preventOverlap: false';
|
||||
container.appendChild(descriptionDiv);
|
||||
|
||||
const width = container.scrollWidth;
|
||||
const height = (container.scrollHeight || 500) - 30;
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
width,
|
||||
height,
|
||||
data,
|
||||
node: (model) => {
|
||||
return {
|
||||
id: model.id,
|
||||
labelText: (d) => model.data.label,
|
||||
};
|
||||
},
|
||||
layout: {
|
||||
type: 'force',
|
||||
linkDistance: 50,
|
||||
animation: true,
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
descriptionDiv.innerHTML = 'Force layout, linkDistance = 100, preventOverlap: true';
|
||||
graph.layout({
|
||||
type: 'force',
|
||||
linkDistance: 100,
|
||||
preventOverlap: true,
|
||||
nodeSize: 20,
|
||||
animation: true,
|
||||
});
|
||||
}, 5000);
|
||||
|
||||
graph.render();
|
@ -1,65 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data: {
|
||||
nodes: [
|
||||
{ id: 'node0', size: 50 },
|
||||
{ id: 'node1', size: 30 },
|
||||
{ id: 'node2', size: 30 },
|
||||
{ id: 'node3', size: 30 },
|
||||
{ id: 'node4', size: 30, isLeaf: true },
|
||||
{ id: 'node5', size: 30, isLeaf: true },
|
||||
{ id: 'node6', size: 15, isLeaf: true },
|
||||
{ id: 'node7', size: 15, isLeaf: true },
|
||||
{ id: 'node8', size: 15, isLeaf: true },
|
||||
{ id: 'node9', size: 15, isLeaf: true },
|
||||
{ id: 'node10', size: 15, isLeaf: true },
|
||||
{ id: 'node11', size: 15, isLeaf: true },
|
||||
{ id: 'node12', size: 15, isLeaf: true },
|
||||
{ id: 'node13', size: 15, isLeaf: true },
|
||||
{ id: 'node14', size: 15, isLeaf: true },
|
||||
{ id: 'node15', size: 15, isLeaf: true },
|
||||
{ id: 'node16', size: 15, isLeaf: true },
|
||||
],
|
||||
edges: [
|
||||
{ source: 'node0', target: 'node1' },
|
||||
{ source: 'node0', target: 'node2' },
|
||||
{ source: 'node0', target: 'node3' },
|
||||
{ source: 'node0', target: 'node4' },
|
||||
{ source: 'node0', target: 'node5' },
|
||||
{ source: 'node1', target: 'node6' },
|
||||
{ source: 'node1', target: 'node7' },
|
||||
{ source: 'node2', target: 'node8' },
|
||||
{ source: 'node2', target: 'node9' },
|
||||
{ source: 'node2', target: 'node10' },
|
||||
{ source: 'node2', target: 'node11' },
|
||||
{ source: 'node2', target: 'node12' },
|
||||
{ source: 'node2', target: 'node13' },
|
||||
{ source: 'node3', target: 'node14' },
|
||||
{ source: 'node3', target: 'node15' },
|
||||
{ source: 'node3', target: 'node16' },
|
||||
],
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: (d) => d.size,
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'force',
|
||||
preventOverlap: true,
|
||||
animation: true,
|
||||
linkDistance: (d) => {
|
||||
if (d.source === 'node0' || d.target === 'node0') {
|
||||
return 200;
|
||||
}
|
||||
return 80;
|
||||
},
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas'],
|
||||
autoResize: true,
|
||||
zoomRange: [0.1, 5],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -1,40 +0,0 @@
|
||||
{
|
||||
"title": {
|
||||
"zh": "中文分类",
|
||||
"en": "Category"
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicForce.js",
|
||||
"title": {
|
||||
"zh": "Force 聚类及固定拖拽节点",
|
||||
"en": "Clustering Force Layout with dragging"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sA14SZo9BBMAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "basicFA2.js",
|
||||
"title": {
|
||||
"zh": "基本 Force Atlas 2",
|
||||
"en": "Basic Force-Atlas 2 Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-HgiS6CyuuEAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "forceDirectedFunctionalParams.js",
|
||||
"title": {
|
||||
"zh": "定制不同节点的参数",
|
||||
"en": "Different Configurations for Nodes"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*xQRmQ7pTvZMAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "forceDirectedConfigurationTranslate.js",
|
||||
"title": {
|
||||
"zh": "力导向布局参数动态变化",
|
||||
"en": "Update Configurations for Force-directed Layout"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*2HKeQqGwjQoAAAAAAAAAAAAADmJ7AQ/original"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
title: Force-directed Layout
|
||||
order: 0
|
||||
---
|
||||
|
||||
Force-directed layout is a set of algorithms which are imporved and extended by lots of researchers based on the earliest classical force-directed algorithm. They simulate the nodes and edges in the graph as the physical objects. There are attractive forces and repulsive forces between nodes to iteratively move them to reach a reasonable layout.
|
||||
|
||||
## Usage
|
||||
|
||||
The classical force-directed layout in G6 comes from d3.js. As the demo below, you can deploy it in `layout` while instantiating Graph. it can also be used for [Subgraph Layout](/en/docs/manual/middle/layout/sub-layout).
|
||||
|
||||
- Example 1 : Basic force-directed layout and dragging interactions.
|
||||
- Example 2 : Prevent node overlappings.
|
||||
- Example 3 : Adjust the link distances and forces for different nodes.
|
||||
- Example 4 : Fix the dragged node.
|
||||
- Example 5 : Translate the layout parameters in dynamic.
|
||||
- Example 6 : The bubbles layout and interactions.
|
||||
- Example 7 : Constrain the layout in a certain area.
|
@ -1,18 +0,0 @@
|
||||
---
|
||||
title: 力导向图布局
|
||||
order: 0
|
||||
---
|
||||
|
||||
力导向图布局作为较早被发明的一种实际应用布局算法,经过研究者多年改进、扩展,已发展成为一类算法的集合。该类算法的特点是模拟物理世界中的作用力,施加在节点上,并迭代计算以达到合理放置节点、美观布局的一类算法。
|
||||
|
||||
## 使用指南
|
||||
|
||||
G6 内置的经典力导向算法引用了 d3.js 的力导向算法。如下面代码所示,可在实例化 Graph 时使用该布局。除此之外,还可以如[子图布局](/zh/docs/manual/middle/layout/sub-layout)所示单独使用布局。
|
||||
|
||||
- 代码演示 1 :基础的经典力导向布局及节点的拖拽。
|
||||
- 代码演示 2 :节点不重叠。
|
||||
- 代码演示 3 :为不同节点调整边长和力。
|
||||
- 代码演示 4 :固定被拖拽的节点。
|
||||
- 代码演示 5 :支持布局参数的动态切换。
|
||||
- 代码演示 6 :使用力导向算法实现气泡效果及交互。
|
||||
- 代码演示 7 :约束在一定范围内进行力导向布局。
|
32
packages/site/examples/layout/fruchterman/demo/basic.js
Normal file
32
packages/site/examples/layout/fruchterman/demo/basic.js
Normal file
@ -0,0 +1,32 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cluster.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'fruchterman',
|
||||
gravity: 5,
|
||||
speed: 5,
|
||||
animated: true,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelPlacement: 'center',
|
||||
labelText: (d) => d.id,
|
||||
labelBackground: false,
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
animation: true,
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
38
packages/site/examples/layout/fruchterman/demo/cluster.js
Normal file
38
packages/site/examples/layout/fruchterman/demo/cluster.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cluster.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'fruchterman',
|
||||
gravity: 10,
|
||||
speed: 5,
|
||||
clustering: true,
|
||||
nodeClusterBy: 'cluster',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelPlacement: 'center',
|
||||
labelText: (d) => d.id,
|
||||
labelBackground: false,
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: true,
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
animation: true,
|
||||
});
|
||||
|
||||
graph.render();
|
||||
});
|
@ -5,7 +5,7 @@
|
||||
},
|
||||
"demos": [
|
||||
{
|
||||
"filename": "basicFruchterman.ts",
|
||||
"filename": "basic.js",
|
||||
"title": {
|
||||
"zh": "基本 Fruchterman 布局",
|
||||
"en": "Basic Fruchterman Layout"
|
||||
@ -13,7 +13,7 @@
|
||||
"screenshot": "https://gw.alipayobjects.com/mdn/rms_f8c6a0/afts/img/A*1KY7SLEXxqMAAAAAAAAAAABkARQnAQ"
|
||||
},
|
||||
{
|
||||
"filename": "fruchtermanCluster.ts",
|
||||
"filename": "cluster.js",
|
||||
"title": {
|
||||
"zh": "基本 Fruchterman 布局",
|
||||
"en": "Basic Fruchterman Layout"
|
||||
@ -21,20 +21,20 @@
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*-s9CTphuwgcAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "fruchtermanWebWorker.ts",
|
||||
"filename": "run-in-web-worker.js",
|
||||
"title": {
|
||||
"zh": "Fruchterman 使用 Web-worker",
|
||||
"en": "Fruchterman with Web-worker"
|
||||
"zh": "使用 Web-worker",
|
||||
"en": "Run in Web-worker"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*3gn9TZ3oUoIAAAAAAAAAAAAADmJ7AQ/original"
|
||||
},
|
||||
{
|
||||
"filename": "fruchtermanFix.ts",
|
||||
"filename": "run-in-gpu.js",
|
||||
"title": {
|
||||
"zh": "Fruchterman 固定被拖拽的节点",
|
||||
"en": "Fruchterman with Fixing Dragged Nodes"
|
||||
"zh": "使用 GPU 加速",
|
||||
"en": "Run in GPU"
|
||||
},
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*sbvuTbp3L6sAAAAAAAAAAAAADmJ7AQ/original"
|
||||
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*SmXBQ6fv8PoAAAAAAAAAAAAADmJ7AQ/original"
|
||||
}
|
||||
]
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import { Graph, register } from '@antv/g6';
|
||||
import { FruchtermanLayout } from '@antv/layout-gpu';
|
||||
|
||||
// Resister the layout into G6.
|
||||
register('layout', 'fruchterman-gpu', FruchtermanLayout);
|
||||
|
||||
fetch('https://gw.alipayobjects.com/os/basement_prod/7bacd7d1-4119-4ac1-8be3-4c4b9bcbc25f.json')
|
||||
@ -17,15 +16,17 @@ fetch('https://gw.alipayobjects.com/os/basement_prod/7bacd7d1-4119-4ac1-8be3-4c4
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
opacity: 0.5,
|
||||
endArrow: true,
|
||||
endArrowSize: 2,
|
||||
startArrow: true,
|
||||
},
|
||||
},
|
||||
layout: {
|
||||
type: 'fruchterman-gpu',
|
||||
type: 'fruchterman',
|
||||
speed: 20,
|
||||
gravity: 1,
|
||||
maxIteration: 10000,
|
||||
workerEnabled: true,
|
||||
},
|
||||
behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element', 'click-select'],
|
||||
behaviors: ['zoom-canvas', 'drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
@ -0,0 +1,43 @@
|
||||
import { Graph, GraphEvent } from '@antv/g6';
|
||||
|
||||
fetch('https://assets.antv.antgroup.com/g6/cluster.json')
|
||||
.then((res) => res.json())
|
||||
.then((data) => {
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'fruchterman',
|
||||
speed: 20,
|
||||
gravity: 10,
|
||||
maxIteration: 10000,
|
||||
workerEnabled: true,
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
labelText: (d) => d.id,
|
||||
labelPlacement: 'center',
|
||||
},
|
||||
palette: {
|
||||
type: 'group',
|
||||
field: 'cluster',
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
stroke: '#ddd',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
});
|
||||
|
||||
graph.render();
|
||||
|
||||
window.addPanel((gui) => {
|
||||
const msg = gui.add({ msg: 'Running...' }, 'msg').name('Tips').disable();
|
||||
graph.on(GraphEvent.AFTER_LAYOUT, () => {
|
||||
msg.setValue('Layout Done!');
|
||||
});
|
||||
});
|
||||
});
|
4
packages/site/examples/layout/fruchterman/index.en.md
Normal file
4
packages/site/examples/layout/fruchterman/index.en.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Fruchterman Layout
|
||||
order: 13
|
||||
---
|
4
packages/site/examples/layout/fruchterman/index.zh.md
Normal file
4
packages/site/examples/layout/fruchterman/index.zh.md
Normal file
@ -0,0 +1,4 @@
|
||||
---
|
||||
title: Fruchterman 图布局
|
||||
order: 13
|
||||
---
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/fruchterman.en.md"></embed>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
title: API
|
||||
---
|
||||
|
||||
<embed src="@/docs/api/graphLayout/fruchterman.zh.md"></embed>
|
@ -1,135 +0,0 @@
|
||||
import { Graph } from '@antv/g6';
|
||||
|
||||
const data = {
|
||||
nodes: [
|
||||
{ id: '0', data: { cluster: 'a' } },
|
||||
{ id: '1', data: { cluster: 'a' } },
|
||||
{ id: '2', data: { cluster: 'a' } },
|
||||
{ id: '3', data: { cluster: 'a' } },
|
||||
{ id: '4', data: { cluster: 'a' } },
|
||||
{ id: '5', data: { cluster: 'a' } },
|
||||
{ id: '6', data: { cluster: 'a' } },
|
||||
{ id: '7', data: { cluster: 'a' } },
|
||||
{ id: '8', data: { cluster: 'a' } },
|
||||
{ id: '9', data: { cluster: 'a' } },
|
||||
{ id: '10', data: { cluster: 'a' } },
|
||||
{ id: '11', data: { cluster: 'a' } },
|
||||
{ id: '12', data: { cluster: 'a' } },
|
||||
{ id: '13', data: { cluster: 'b' } },
|
||||
{ id: '14', data: { cluster: 'b' } },
|
||||
{ id: '15', data: { cluster: 'b' } },
|
||||
{ id: '16', data: { cluster: 'b' } },
|
||||
{ id: '17', data: { cluster: 'b' } },
|
||||
{ id: '18', data: { cluster: 'c' } },
|
||||
{ id: '19', data: { cluster: 'c' } },
|
||||
{ id: '20', data: { cluster: 'c' } },
|
||||
{ id: '21', data: { cluster: 'c' } },
|
||||
{ id: '22', data: { cluster: 'c' } },
|
||||
{ id: '23', data: { cluster: 'c' } },
|
||||
{ id: '24', data: { cluster: 'c' } },
|
||||
{ id: '25', data: { cluster: 'c' } },
|
||||
{ id: '26', data: { cluster: 'c' } },
|
||||
{ id: '27', data: { cluster: 'c' } },
|
||||
{ id: '28', data: { cluster: 'c' } },
|
||||
{ id: '29', data: { cluster: 'c' } },
|
||||
{ id: '30', data: { cluster: 'c' } },
|
||||
{ id: '31', data: { cluster: 'd' } },
|
||||
{ id: '32', data: { cluster: 'd' } },
|
||||
{ id: '33', data: { cluster: 'd' } },
|
||||
],
|
||||
edges: [
|
||||
{ source: '0', target: '1' },
|
||||
{ source: '0', target: '2' },
|
||||
{ source: '0', target: '3' },
|
||||
{ source: '0', target: '4' },
|
||||
{ source: '0', target: '5' },
|
||||
{ source: '0', target: '7' },
|
||||
{ source: '0', target: '8' },
|
||||
{ source: '0', target: '9' },
|
||||
{ source: '0', target: '10' },
|
||||
{ source: '0', target: '11' },
|
||||
{ source: '0', target: '13' },
|
||||
{ source: '0', target: '14' },
|
||||
{ source: '0', target: '15' },
|
||||
{ source: '0', target: '16' },
|
||||
{ source: '2', target: '3' },
|
||||
{ source: '4', target: '5' },
|
||||
{ source: '4', target: '6' },
|
||||
{ source: '5', target: '6' },
|
||||
{ source: '7', target: '13' },
|
||||
{ source: '8', target: '14' },
|
||||
{ source: '9', target: '10' },
|
||||
{ source: '10', target: '22' },
|
||||
{ source: '10', target: '14' },
|
||||
{ source: '10', target: '12' },
|
||||
{ source: '10', target: '24' },
|
||||
{ source: '10', target: '21' },
|
||||
{ source: '10', target: '20' },
|
||||
{ source: '11', target: '24' },
|
||||
{ source: '11', target: '22' },
|
||||
{ source: '11', target: '14' },
|
||||
{ source: '12', target: '13' },
|
||||
{ source: '16', target: '17' },
|
||||
{ source: '16', target: '18' },
|
||||
{ source: '16', target: '21' },
|
||||
{ source: '16', target: '22' },
|
||||
{ source: '17', target: '18' },
|
||||
{ source: '17', target: '20' },
|
||||
{ source: '18', target: '19' },
|
||||
{ source: '19', target: '20' },
|
||||
{ source: '19', target: '33' },
|
||||
{ source: '19', target: '22' },
|
||||
{ source: '19', target: '23' },
|
||||
{ source: '20', target: '21' },
|
||||
{ source: '21', target: '22' },
|
||||
{ source: '22', target: '24' },
|
||||
{ source: '22', target: '25' },
|
||||
{ source: '22', target: '26' },
|
||||
{ source: '22', target: '23' },
|
||||
{ source: '22', target: '28' },
|
||||
{ source: '22', target: '30' },
|
||||
{ source: '22', target: '31' },
|
||||
{ source: '22', target: '32' },
|
||||
{ source: '22', target: '33' },
|
||||
{ source: '23', target: '28' },
|
||||
{ source: '23', target: '27' },
|
||||
{ source: '23', target: '29' },
|
||||
{ source: '23', target: '30' },
|
||||
{ source: '23', target: '31' },
|
||||
{ source: '23', target: '33' },
|
||||
{ source: '32', target: '33' },
|
||||
],
|
||||
};
|
||||
|
||||
const graph = new Graph({
|
||||
container: 'container',
|
||||
data,
|
||||
layout: {
|
||||
type: 'fruchterman',
|
||||
gravity: 10,
|
||||
speed: 5,
|
||||
clustering: true,
|
||||
nodeClusterBy: 'cluster',
|
||||
},
|
||||
node: {
|
||||
style: {
|
||||
size: 20,
|
||||
stroke: '#5B8FF9',
|
||||
fill: '#C6E5FF',
|
||||
lineWidth: 1,
|
||||
labelPlacement: 'center',
|
||||
labelText: (d) => d.id,
|
||||
labelBackground: false,
|
||||
},
|
||||
},
|
||||
edge: {
|
||||
style: {
|
||||
endArrow: true,
|
||||
endArrowPath: 'M 0,0 L 4,2 L 4,-2 Z',
|
||||
},
|
||||
},
|
||||
behaviors: ['drag-canvas', 'drag-element'],
|
||||
animation: true,
|
||||
});
|
||||
|
||||
graph.render();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user