admin-vue3/src/components/wu-flow-lib/utils/shape-register.ts

216 lines
6.5 KiB
TypeScript

import { Graph, CellRenderer, Shape } from '@maxgraph/core';
import { FlowIcons, UMLIcons } from '../icons';
export class ShapeRegister {
static registerCustomShapes() {
// 注册基础流程图形状
CellRenderer.registerShape('start', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
// 绘制圆形
c.ellipse(x, y, w, h);
c.fillAndStroke();
// 绘制内部小圆
const insetSize = Math.min(w, h) * 0.3;
c.setFillColor('#4caf50');
c.ellipse(x + (w-insetSize)/2, y + (h-insetSize)/2, insetSize, insetSize);
c.fill();
}
});
CellRenderer.registerShape('end', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
// 绘制圆形
c.ellipse(x, y, w, h);
c.fillAndStroke();
// 绘制内部圆环
const insetSize = Math.min(w, h) * 0.3;
c.setStrokeWidth(2);
c.setStrokeColor('#f44336');
c.ellipse(x + (w-insetSize)/2, y + (h-insetSize)/2, insetSize, insetSize);
c.stroke();
}
});
// 注册 UML 图形状
Object.entries(UMLIcons).forEach(([name, svg]) => {
CellRenderer.registerShape(name.toLowerCase(), class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
c.rect(x, y, w, h);
c.fillAndStroke();
if (this.state.style.shape === name.toLowerCase()) {
const svgElement = new DOMParser().parseFromString(svg, 'image/svg+xml').documentElement;
const svgContent = svgElement.innerHTML;
c.setSvg(svgContent, x, y, w, h);
}
}
});
});
// 注册 UML 类图形状
CellRenderer.registerShape('umlClass', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
c.rect(x, y, w, h);
c.fillAndStroke();
// 绘制分隔线
const headerHeight = h / 3;
c.begin();
c.moveTo(x, y + headerHeight);
c.lineTo(x + w, y + headerHeight);
c.moveTo(x, y + headerHeight * 2);
c.lineTo(x + w, y + headerHeight * 2);
c.stroke();
}
});
// 注册 UML 接口形状
CellRenderer.registerShape('umlInterface', class extends Shape {
constructor(state: any) {
super(state);
this.isDashed = true;
}
paintBackground(c: any, x: number, y: number, w: number, h: number) {
c.setDashed(true, [2, 2]);
c.rect(x, y, w, h);
c.fillAndStroke();
// 绘制分隔线
const headerHeight = h / 3;
c.begin();
c.moveTo(x, y + headerHeight);
c.lineTo(x + w, y + headerHeight);
c.moveTo(x, y + headerHeight * 2);
c.lineTo(x + w, y + headerHeight * 2);
c.stroke();
}
});
// 注册包形状
CellRenderer.registerShape('package', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
const tabWidth = w * 0.3;
const tabHeight = h * 0.2;
c.begin();
// 绘制标签部分
c.moveTo(x, y);
c.lineTo(x + tabWidth, y);
c.lineTo(x + tabWidth, y + tabHeight);
c.lineTo(x + w, y + tabHeight);
c.lineTo(x + w, y + h);
c.lineTo(x, y + h);
c.close();
c.fillAndStroke();
}
});
// 注册组件形状
CellRenderer.registerShape('component', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
c.rect(x, y, w, h);
c.fillAndStroke();
const portSize = Math.min(w, h) * 0.2;
// 绘制端口
c.begin();
c.rect(x - portSize, y + h * 0.25, portSize, portSize);
c.rect(x - portSize, y + h * 0.6, portSize, portSize);
c.fillAndStroke();
}
});
// 注册备注形状
CellRenderer.registerShape('note', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
const fold = Math.min(w, h) * 0.2; // 折角大小
c.begin();
c.moveTo(x, y);
c.lineTo(x + w - fold, y);
c.lineTo(x + w, y + fold);
c.lineTo(x + w, y + h);
c.lineTo(x, y + h);
c.close();
c.fillAndStroke();
// 绘制折角
c.begin();
c.moveTo(x + w - fold, y);
c.lineTo(x + w - fold, y + fold);
c.lineTo(x + w, y + fold);
c.stroke();
}
});
// 注册五角星形状
CellRenderer.registerShape('star', class extends Shape {
paintBackground(c: any, x: number, y: number, w: number, h: number) {
const cx = x + w/2;
const cy = y + h/2;
const r = Math.min(w, h)/2;
const points = [];
for (let i = 0; i < 5; i++) {
// 外部点
const angle = (i * 72 - 90) * Math.PI/180;
points.push([
cx + r * Math.cos(angle),
cy + r * Math.sin(angle)
]);
// 内部点
const innerAngle = ((i * 72 + 36) - 90) * Math.PI/180;
points.push([
cx + (r/2) * Math.cos(innerAngle),
cy + (r/2) * Math.sin(innerAngle)
]);
}
c.begin();
c.moveTo(points[0][0], points[0][1]);
for (let i = 1; i < points.length; i++) {
c.lineTo(points[i][0], points[i][1]);
}
c.lineTo(points[0][0], points[0][1]);
c.close();
c.fillAndStroke();
}
});
// 注册表格形状
// graph.getStylesheet().putCellStyle('table', {
// shape: 'html',
// whiteSpace: 'wrap',
// verticalAlign: 'top',
// align: 'left',
// overflow: 'visible'
// });
// // 注册泳道形状
// CellRenderer.registerShape('swimlane', class extends Shape {
// paintBackground(c: any, x: number, y: number, w: number, h: number) {
// const style = this.state.style;
// const isHorizontal = style.horizontal;
// const startSize = style.startSize || 30;
// // 绘制外框
// c.begin();
// c.rect(x, y, w, h);
// c.fillAndStroke();
// // 绘制标题区域
// c.begin();
// if (isHorizontal) {
// c.rect(x, y, w, startSize);
// } else {
// c.rect(x, y, startSize, h);
// }
// c.fillAndStroke();
// }
// });
}
}