Skip to content

Commit

Permalink
docs: add snake flow diagram (#6581)
Browse files Browse the repository at this point in the history
* docs: add snake flow diagram

* fix: snake polyline
  • Loading branch information
yvonneyx authored Nov 29, 2024
1 parent 3ef6d94 commit 2f58671
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 0 deletions.
8 changes: 8 additions & 0 deletions packages/site/examples/scene-case/default/demo/meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@
"en": "Why Do Cats?"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*ug4vTJA7QbMAAAAAAAAAAAAADmJ7AQ/original"
},
{
"filename": "snake-flow-diagram.js",
"title": {
"zh": "S 型流程图",
"en": "Snake Flow Diagram"
},
"screenshot": "https://mdn.alipayobjects.com/huamei_qa8qxu/afts/img/A*7L51SLW2WhcAAAAAAAAAAAAADmJ7AQ/original"
}
]
}
149 changes: 149 additions & 0 deletions packages/site/examples/scene-case/default/demo/snake-flow-diagram.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import { BaseLayout, ExtensionCategory, Graph, Polyline, positionOf, register } from '@antv/g6';

const data = {
nodes: [
{ id: '0', data: { label: '开始流程', time: '17:00:00' } },
{ id: '1', data: { label: '流程1', time: '17:00:05' } },
{ id: '2', data: { label: '流程2', time: '17:00:12' } },
{ id: '3', data: { label: '流程3', time: '17:00:30' } },
{ id: '4', data: { label: '流程4', time: '17:02:00' } },
{ id: '5', data: { label: '流程5', time: '17:02:40' } },
{ id: '6', data: { label: '流程6', time: '17:05:50' } },
{ id: '7', data: { label: '流程7', time: '17:10:00' } },
{ id: '8', data: { label: '流程8', time: '17:11:20' } },
{ id: '9', data: { label: '流程9', time: '17:15:00' } },
{ id: '10', data: { label: '流程10', time: '17:30:00' } },
{ id: '11', data: { label: '流程11' } },
{ id: '12', data: { label: '流程12' } },
{ id: '13', data: { label: '流程13' } },
{ id: '14', data: { label: '流程14' } },
{ id: '15', data: { label: '流程结束' } },
],
edges: [
{ source: '0', target: '1', data: { done: true } },
{ source: '1', target: '2', data: { done: true } },
{ source: '2', target: '3', data: { done: true } },
{ source: '3', target: '4', data: { done: true } },
{ source: '4', target: '5', data: { done: true } },
{ source: '5', target: '6', data: { done: true } },
{ source: '6', target: '7', data: { done: true } },
{ source: '7', target: '8', data: { done: true } },
{ source: '8', target: '9', data: { done: true } },
{ source: '9', target: '10', data: { done: true } },
{ source: '10', target: '11', data: { done: false } },
{ source: '11', target: '12', data: { done: false } },
{ source: '12', target: '13', data: { done: false } },
{ source: '13', target: '14', data: { done: false } },
{ source: '14', target: '15', data: { done: false } },
],
};

class SnakeLayout extends BaseLayout {
id = 's-layout';

async execute(data, options) {
const {
width,
height,
nodeSize = 32,
cols = 5,
sep: propSep,
nodeSep: propNodeSep,
} = { ...this.options, ...options };

const totalRows = Math.ceil(data.nodes.length / cols);
const sep = propSep ? propSep : height / (totalRows - 1) - nodeSize;
const nodeSep = propNodeSep ? propNodeSep : width / cols - nodeSize;

const nodes = data.nodes.map((node, index) => {
const row = Math.floor(index / cols);
const col = index % cols;
const x = (col + 0.5) * (nodeSize + nodeSep);

let y = row * (nodeSize + sep);
if (row === 0) y += nodeSize / 2;
if (row === totalRows - 1) y -= nodeSize / 2;

const adjustedX = row % 2 === 0 ? x : (cols - col - 0.5) * (nodeSize + nodeSep);

return {
id: node.id,
style: { x: adjustedX, y },
};
});

return { nodes };
}
}

class SnakePolyline extends Polyline {
getPoints(attributes) {
const [sourcePoint, targetPoint] = this.getEndpoints(attributes, false);

if (sourcePoint[1] === targetPoint[1]) return [sourcePoint, targetPoint];

const prevPointId = this.context.model
.getRelatedEdgesData(this.sourceNode.id)
.filter((edge) => edge.target === this.sourceNode.id)[0]?.source;
if (!prevPointId) return [sourcePoint, targetPoint];

const prevPoint = positionOf(this.context.model.getNodeLikeDatum(prevPointId));
const offset = -(prevPoint[0] - sourcePoint[0]) / 2;
return [
sourcePoint,
[sourcePoint[0] + offset, sourcePoint[1]],
[targetPoint[0] + offset, targetPoint[1]],
targetPoint,
];
}
}

register(ExtensionCategory.LAYOUT, 's-layout', SnakeLayout);
register(ExtensionCategory.EDGE, 's-polyline', SnakePolyline);

const graph = new Graph({
container: 'container',
data,
animation: false,
background: '#fafafa',
autoFit: 'center',
node: {
style: {
fill: (d) => (d.data.time ? '#1783ff' : '#d9d9d9'),
lineWidth: 2,
size: 8,
stroke: (d) => (d.data.time ? 'lightblue' : ''),
labelFontWeight: 500,
labelOffsetY: 8,
labelText: (d) => d.data.label,
badge: true,
badges: (d) => [
{
background: false,
fill: '#858ca6',
fontSize: 10,
offsetY: 39,
placement: 'bottom',
text: d.data.time || '--',
},
],
},
},
edge: {
type: 's-polyline',
style: {
lineWidth: 2,
stroke: (d) => (d.data.done ? '#1783ff' : '#d9d9d9'),
},
},
layout: {
type: 's-layout',
cols: 6,
sep: 120,
nodeSep: 80,
nodeSize: 32,
},
behaviors: ['drag-canvas', 'zoom-canvas'],
});

graph.render();

0 comments on commit 2f58671

Please sign in to comment.