216 lines
6.5 KiB
TypeScript
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();
|
|
// }
|
|
// });
|
|
}
|
|
}
|