hookehuyr

feat: 新增release页面和自定义多边形节点

新增release.vue页面,用于展示拖拽面板。在node-model中新增自定义多边形节点,并更新相关路由和依赖配置。
This diff is collapsed. Click to expand it.
......@@ -145,6 +145,11 @@ const router = createRouter({
name: 'api-transform-model',
component: () => import('../views/api/transformModel.vue')
},
{
path: '/release',
name: 'release',
component: () => import('../views/release.vue')
},
]
})
......
<!--
* @Date: 2025-03-10 16:52:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-19 00:57:55
* @LastEditTime: 2025-03-19 10:46:41
* @FilePath: /logic-flow2/src/views/api/transformModel.vue
* @Description: 拖拽面板
-->
......@@ -59,14 +59,17 @@ const centerView = () => {
if (nodes.length === 0) return;
// 计算所有节点的边界框
const bounds = nodes.reduce((acc, node) => {
const { x, y } = node;
acc.minX = Math.min(acc.minX, x);
acc.maxX = Math.max(acc.maxX, x);
acc.minY = Math.min(acc.minY, y);
acc.maxY = Math.max(acc.maxY, y);
return acc;
}, { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity });
const bounds = nodes.reduce(
(acc, node) => {
const { x, y } = node;
acc.minX = Math.min(acc.minX, x);
acc.maxX = Math.max(acc.maxX, x);
acc.minY = Math.min(acc.minY, y);
acc.maxY = Math.max(acc.maxY, y);
return acc;
},
{ minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
);
// 计算中心点和范围
const centerX = (bounds.minX + bounds.maxX) / 2;
......@@ -82,6 +85,7 @@ onMounted(() => {
lf = new LogicFlow({
container: container.value,
grid: true,
nodeTextDraggable: true,
});
// 监听点击画布功能
......@@ -89,12 +93,11 @@ onMounted(() => {
console.log("Canvas clicked at:", e.x, e.y);
});
lf.on('node:click', (e) => {
lf.on("node:click", (e) => {
console.log(e);
// 示例:HTML坐标转换为画布坐标
console.warn(e);
const htmlPoint = { x: 100, y: 100 };
const { transformModel } = lf.graphModel;
const canvasPoint = transformModel.HtmlPointToCanvasPoint(htmlPoint);
......@@ -116,14 +119,17 @@ onMounted(() => {
const nodes = lf.graphModel.nodes;
if (nodes.length === 0) return;
const bounds = nodes.reduce((acc, node) => {
const { x, y } = node;
acc.minX = Math.min(acc.minX, x);
acc.maxX = Math.max(acc.maxX, x);
acc.minY = Math.min(acc.minY, y);
acc.maxY = Math.max(acc.maxY, y);
return acc;
}, { minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity });
const bounds = nodes.reduce(
(acc, node) => {
const { x, y } = node;
acc.minX = Math.min(acc.minX, x);
acc.maxX = Math.max(acc.maxX, x);
acc.minY = Math.min(acc.minY, y);
acc.maxY = Math.max(acc.maxY, y);
return acc;
},
{ minX: Infinity, maxX: -Infinity, minY: Infinity, maxY: -Infinity }
);
const centerX = (bounds.minX + bounds.maxX) / 2;
const centerY = (bounds.minY + bounds.maxY) / 2;
......@@ -133,7 +139,10 @@ onMounted(() => {
// transformModel.focusOn(centerX, centerY, width, height);
}, 0);
const { editConfigModel } = lf.graphModel;
editConfigModel.updateEditConfig({
stopZoomGraph: true,
});
});
</script>
......
/*
* @Date: 2025-03-19 17:24:14
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-19 17:24:38
* @FilePath: /logic-flow2/src/views/node-model/customPolygon.js
* @Description: 文件描述
*/
import { PolygonNode, PolygonNodeModel } from '@logicflow/core';
class CustomPolygonModel extends PolygonNodeModel {
// 默认四边形 => 八边形
setAttributes() {
const width = 100;
const height = 100;
const x = 50;
const y = 50;
// 计算多边形的八个顶点, 中心点为[50, 50], 宽高均为100
const pointList = [
[x - 0.205 * width, y - 0.5 * height],
[x + 0.205 * width, y - 0.5 * height],
[x + 0.5 * width, y - 0.205 * height],
[x + 0.5 * width, y + 0.205 * height],
[x + 0.205 * width, y + 0.5 * height],
[x - 0.205 * width, y + 0.5 * height],
[x - 0.5 * width, y + 0.205 * height],
[x - 0.5 * width, y - 0.205 * height],
];
this.points = pointList;
}
getTextStyle() {
const { refX = 0, refY = 0 } = this.properties;
const style = super.getTextStyle();
// 通过 transform 重新设置 text 的位置:向下移动70px
return {
...style,
transform: `matrix(1 0 0 1 ${refX} ${refY + 70})`,
};
}
}
export default {
type: 'custom-polygon',
view: PolygonNode,
model: CustomPolygonModel,
};
/*
* @Date: 2025-03-11 15:09:49
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-11 15:45:06
* @FilePath: /logic-flow2/src/views/node/data.js
* @LastEditTime: 2025-03-19 17:26:16
* @FilePath: /logic-flow2/src/views/node-model/data.js
* @Description: 文件描述
*/
export default {
......@@ -47,5 +47,12 @@ export default {
height: 130,
},
},
{
id: '4',
type: 'custom-polygon',
x: 100,
y: 300,
text: 'custom-polygon',
}
],
};
......
<!--
* @Date: 2025-03-11 15:07:29
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-11 16:18:37
* @FilePath: /logic-flow2/src/views/node/index.vue
* @LastEditTime: 2025-03-19 17:31:46
* @FilePath: /logic-flow2/src/views/node-model/index.vue
* @Description: 自定义节点model
-->
<template>
......@@ -12,9 +12,10 @@
</template>
<script setup>
import LogicFlow from '@logicflow/core';
import UserTask from './customRect';
import data from './data';
import LogicFlow from "@logicflow/core";
import UserTask from "./customRect";
import customPolygon from "./customPolygon";
import data from "./data";
const SilentConfig = {
isSilentMode: true,
......@@ -35,6 +36,15 @@ onMounted(() => {
});
lf.register(UserTask);
lf.register(customPolygon);
lf.on("node:click", ({ data }) => {
if (data.type === "custom-polygon") {
const node = lf.getNodeModelById(data.id);
console.log("节点顶点坐标:", node.points);
}
});
lf.render(data);
lf.translateCenter();
});
......
<!--
* @Date: 2025-03-10 16:52:35
* @LastEditors: hookehuyr hookehuyr@gmail.com
* @LastEditTime: 2025-03-19 11:32:33
* @FilePath: /logic-flow2/src/views/release.vue
* @Description: 拖拽面板
-->
<template>
<div class="container">
<div ref="container" class="flow-container"></div>
</div>
</template>
<script setup>
import LogicFlow from "@logicflow/core";
const container = ref(null);
let lf = null;
onMounted(() => {
lf = new LogicFlow({
container: container.value,
grid: true,
nodeTextDraggable: true,
nodeTextEdit: true,
edgeTextEdit: true,
stopScrollGraph: true,
stopZoomGraph: false,
style: {
rect: {
width: 100,
height: 50,
radius: 8,
},
circle: {
r: 30,
},
},
});
lf.render({
nodes: [
{
id: "start",
type: "rect",
x: 200,
y: 100,
text: "开始",
properties: {
nodeType: "start",
style: {
fill: "#e8f7ff",
stroke: "#1890ff",
strokeWidth: 2,
},
textStyle: {
color: "#1890ff",
fontSize: 16,
fontWeight: "bold",
},
},
},
{
id: "process",
type: "circle",
x: 400,
y: 100,
text: "处理",
properties: {
nodeType: "process",
style: {
fill: "#fff7e6",
stroke: "#ffa940",
strokeWidth: 2,
},
},
},
],
edges: [
{
id: "edge1",
sourceNodeId: "start",
targetNodeId: "process",
type: "polyline",
text: "流转",
properties: {
style: {
stroke: "#1890ff",
strokeWidth: 2,
},
},
},
],
});
// 监听节点点击
lf.on("node:click", ({ data }) => {
console.log("点击节点:", data);
});
// 监听连线完成
lf.on("edge:connect", ({ data }) => {
console.log("连线完成:", data);
});
// 监听画布缩放
lf.on("graph:transform", (transform) => {
console.log("画布变换:", transform);
});
// 居中显示
lf.translateCenter();
});
</script>
<style scoped>
.container {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.flow-container {
flex: 1;
width: 100%;
height: 100%;
}
</style>