流程图渲染器多点折线实践
背景:G6的折线无法自定义controlPoints,折线的方案由G6官方自定义的算法生成,会导致画线时线段穿过图形。
解决方案:在绘制折线时,让用户能自定义画转折点,从而达到线段自由弯折,不和图形重叠。
实现效果:
具体方案:
- 利用G6内置直线进行画线,在需要转折的地方按一下ctrl键,利用G6的内置圆形画一个转折点。
- 线段的终点指向转折点,然后又从转折点开启一条新的连线,连线的终点跟着鼠标。
- 记录下画线起点、终点,转折点集合。
- 当线段画线终止时,利用G6内置的折线(polyLine)画一条折线。然后把刚刚记录的转折点赋值给controlPoints。
- 转折点是基于G6的内置图形,本身也是支持拖拽的。在画线结束后,鼠标放上去折线时,隐藏原本的polyLine画线,显示此线段的转折点,并和起点、终点相连。
关键代码:
// 绘制转折小圆点
handleDrawControlPointRect() {
if (!this.edge) return;
const { edge, currentEdgeGroupId, graph } = this;
const { x, y } = this.mouseCoord;
const sourceNodeId = guid();
const newNodeModel = {
id: sourceNodeId,
x,
y,
group: currentEdgeGroupId,
};
const newNode = graph.addItem('node', new VirtulaNode(newNodeModel).getModel());
const lastEdgeModel = {
target: newNodeModel.id,
targetAnchor: 0,
};
let newEdgeModel = {};
// 更新上一次划线的样式
graph.updateItem(edge, new VirtualEdge(lastEdgeModel).getModel());
const sourceEdgeId = guid();
newEdgeModel = {
id: sourceEdgeId,
source: sourceNodeId,
sourceAnchor: 3,
target: {
x,
y,
},
group: currentEdgeGroupId,
};
// 从结束节点重新开始划线
const newEdge = graph.addItem('edge', new VirtualEdge(newEdgeModel).getModel());
// 将小圆点和线条加入到组中
this.edgeGroup[currentEdgeGroupId].data = [...this.edgeGroup[currentEdgeGroupId].data, newNode, newEdge];
this.edgeGroupCopy[currentEdgeGroupId].data = [
...this.edgeGroupCopy[currentEdgeGroupId].data,
sourceNodeId,
sourceEdgeId,
];
this.edgeGroup[currentEdgeGroupId].points = {
...this.edgeGroup[currentEdgeGroupId].points,
[sourceNodeId]: { x, y },
};
this.edgeGroupCopy[currentEdgeGroupId].points = {
...this.edgeGroupCopy[currentEdgeGroupId].points,
[sourceNodeId]: { x, y },
};
this.edge = newEdge;
},
// 删除一个分组 并且删除真实线段
handleRemoveGroup(currentGroupId) {
const { graph } = this;
// 如果是开始节点和起草节点的连线,不进行删除
if (this.edgeGroup[currentGroupId]?.data?.length === 1 || true) {
const tmpEdge = this.edgeGroup[currentGroupId].data[0];
const tmpEdgeModel = tmpEdge?.getModel() ?? {};
// const sourceNode = graph.findById(tmpEdgeModel.source)?.getModel() ?? {};
// if (sourceNode.bizFormType === 'BEGIN_NODE') {
// graph.emit(EventEmit.DeleteBuildInEdge, {
// type: 'warn',
// desc: '内置线条不能删除',
// });
// return;
// }
}
(this.edgeGroup[currentGroupId]?.data || []).forEach((item) => {
!item.destroyed && graph.removeItem(item);
});
// 删除线段
!this.edgeGroup[currentGroupId]?.realEdge?.destroyed && graph.removeItem(this.edgeGroup[currentGroupId]?.realEdge);
// 删除转折点和线条
if (this.edgeGroup[currentGroupId]?.points) {
(Object.keys(this.edgeGroup[currentGroupId].points) || []).forEach((id) => {
const ele = graph.findById(id);
ele && graph.remove(ele);
});
}
globalCurrentEle.setCurrent({});
delete this.edgeGroup[currentGroupId];
delete this.edgeGroupCopy[currentGroupId];
this.edge = null;
graph.emit('test', this.edgeGroupCopy);
},
如何使用:
作者:聂维 创建时间:2022-11-25 15:27
最后编辑:聂维 更新时间:2024-12-11 10:09
最后编辑:聂维 更新时间:2024-12-11 10:09