Showing
5 changed files
with
251 additions
and
2 deletions
| 1 | /* | 1 | /* |
| 2 | * @Date: 2025-03-10 13:15:30 | 2 | * @Date: 2025-03-10 13:15:30 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-12 21:27:32 | 4 | + * @LastEditTime: 2025-03-13 12:13:02 |
| 5 | * @FilePath: /logic-flow2/src/router/index.js | 5 | * @FilePath: /logic-flow2/src/router/index.js |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | */ | 7 | */ |
| ... | @@ -80,6 +80,11 @@ const router = createRouter({ | ... | @@ -80,6 +80,11 @@ const router = createRouter({ |
| 80 | name: 'adv-node-anchor', | 80 | name: 'adv-node-anchor', |
| 81 | component: () => import('../views/adv-node/anchor/index.vue') | 81 | component: () => import('../views/adv-node/anchor/index.vue') |
| 82 | }, | 82 | }, |
| 83 | + { | ||
| 84 | + path: '/adv-edge-animation', | ||
| 85 | + name: 'adv-edge-animation', | ||
| 86 | + component: () => import('../views/adv-edge/animation/index.vue') | ||
| 87 | + }, | ||
| 83 | ] | 88 | ] |
| 84 | }) | 89 | }) |
| 85 | 90 | ... | ... |
src/views/adv-edge/animation/customEdge.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-03-13 12:08:44 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-13 14:11:11 | ||
| 5 | + * @FilePath: /logic-flow2/src/views/adv-edge/animation/customEdge.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +import { h, LineEdge, LineEdgeModel } from '@logicflow/core'; | ||
| 9 | + | ||
| 10 | +// 自定义边的数据模型 | ||
| 11 | +class CustomEdgeModel extends LineEdgeModel { | ||
| 12 | + /** | ||
| 13 | + * 初始化边数据 | ||
| 14 | + * @param {Object} data - 边的初始数据 | ||
| 15 | + */ | ||
| 16 | + initEdgeData(data) { | ||
| 17 | + super.initEdgeData(data); | ||
| 18 | + // 启用自定义文本位置功能 | ||
| 19 | + this.customTextPosition = true; | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + /** | ||
| 23 | + * 设置边的基本属性 | ||
| 24 | + * 启用动画效果 | ||
| 25 | + */ | ||
| 26 | + setAttributes() { | ||
| 27 | + this.isAnimation = true; | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 处理鼠标悬停状态 | ||
| 32 | + * @param {boolean} isHovered - 是否处于悬停状态 | ||
| 33 | + */ | ||
| 34 | + setHovered(isHovered) { | ||
| 35 | + super.setHovered(isHovered); | ||
| 36 | + // 根据悬停状态控制动画 | ||
| 37 | + this.isAnimation = isHovered; | ||
| 38 | + } | ||
| 39 | + | ||
| 40 | + /** | ||
| 41 | + * 获取边的动画样式 | ||
| 42 | + * @returns {Object} 动画样式对象 | ||
| 43 | + */ | ||
| 44 | + getEdgeAnimationStyle() { | ||
| 45 | + const style = super.getEdgeAnimationStyle(); | ||
| 46 | + // 设置虚线样式:5px实线,5px空白 | ||
| 47 | + style.strokeDasharray = '5 5'; | ||
| 48 | + // 设置虚线偏移,实现动画效果 | ||
| 49 | + style.strokeDashoffset = '100%'; | ||
| 50 | + // 设置动画持续时间 | ||
| 51 | + style.animationDuration = '10s'; | ||
| 52 | + return style; | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + /** | ||
| 56 | + * 计算边上文本的位置 | ||
| 57 | + * @returns {Object} 文本位置坐标 | ||
| 58 | + */ | ||
| 59 | + getTextPosition() { | ||
| 60 | + const position = super.getTextPosition(); | ||
| 61 | + // 将点坐标字符串转换为数组 | ||
| 62 | + const currentPositionList = this.points.split(' '); | ||
| 63 | + const pointsList = []; | ||
| 64 | + currentPositionList && | ||
| 65 | + currentPositionList.forEach((item) => { | ||
| 66 | + const [x, y] = item.split(','); | ||
| 67 | + pointsList.push({ x: Number(x), y: Number(y) }); | ||
| 68 | + }); | ||
| 69 | + | ||
| 70 | + if (pointsList.length > 1) { | ||
| 71 | + const { x: x1, y: y1 } = pointsList[0]; | ||
| 72 | + const { x: x2, y: y2 } = pointsList[1]; | ||
| 73 | + let distance = 50; | ||
| 74 | + | ||
| 75 | + // 处理垂直连线的文本位置 | ||
| 76 | + if (x1 === x2) { | ||
| 77 | + if (y2 < y1) { | ||
| 78 | + // 如果是向上的连线,距离取负值 | ||
| 79 | + distance = -50; | ||
| 80 | + } | ||
| 81 | + position.y = y1 + distance; | ||
| 82 | + position.x = x1; | ||
| 83 | + } else { | ||
| 84 | + // 处理水平连线的文本位置 | ||
| 85 | + if (x2 < x1) { | ||
| 86 | + // 如果是向左的连线,距离取负值 | ||
| 87 | + distance = -50; | ||
| 88 | + } | ||
| 89 | + position.x = x1 + distance; | ||
| 90 | + position.y = y1 - 10; | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + return position; | ||
| 94 | + } | ||
| 95 | +} | ||
| 96 | + | ||
| 97 | +// 自定义边的视图 | ||
| 98 | +class CustomEdge extends LineEdge { | ||
| 99 | + /** | ||
| 100 | + * 自定义边的箭头样式 | ||
| 101 | + * @returns {VNode} 箭头的虚拟DOM节点 | ||
| 102 | + */ | ||
| 103 | + getEndArrow() { | ||
| 104 | + const { stroke } = this.props.model.getArrowStyle(); | ||
| 105 | + // 创建一个白色填充的箭头 | ||
| 106 | + return h('path', { | ||
| 107 | + stroke, | ||
| 108 | + fill: '#FFF', | ||
| 109 | + d: 'M 0 0 -10 -5 -10 5 z', // 箭头路径 | ||
| 110 | + }); | ||
| 111 | + } | ||
| 112 | +} | ||
| 113 | + | ||
| 114 | +// 导出自定义边的配置 | ||
| 115 | +export default { | ||
| 116 | + type: 'custom-edge', | ||
| 117 | + model: CustomEdgeModel, | ||
| 118 | + view: CustomEdge, | ||
| 119 | +}; |
src/views/adv-edge/animation/data.js
0 → 100644
| 1 | +/* | ||
| 2 | + * @Date: 2025-03-13 12:08:51 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-13 12:48:22 | ||
| 5 | + * @FilePath: /logic-flow2/src/views/adv-edge/animation/data.js | ||
| 6 | + * @Description: 文件描述 | ||
| 7 | + */ | ||
| 8 | +const data = { | ||
| 9 | + nodes: [ | ||
| 10 | + { | ||
| 11 | + id: 'rect_2', | ||
| 12 | + type: 'circle', | ||
| 13 | + x: 450, | ||
| 14 | + y: 300, | ||
| 15 | + }, | ||
| 16 | + { | ||
| 17 | + id: 'rect_3', | ||
| 18 | + type: 'rect', | ||
| 19 | + x: 150, | ||
| 20 | + y: 400, | ||
| 21 | + }, | ||
| 22 | + { | ||
| 23 | + id: 'rect_9', | ||
| 24 | + type: 'rect', | ||
| 25 | + x: 150, | ||
| 26 | + y: 100, | ||
| 27 | + }, | ||
| 28 | + { | ||
| 29 | + id: 'rect_4', | ||
| 30 | + type: 'rect', | ||
| 31 | + x: 500, | ||
| 32 | + y: 100, | ||
| 33 | + }, | ||
| 34 | + { | ||
| 35 | + id: 'rect_5', | ||
| 36 | + type: 'rect', | ||
| 37 | + x: 150, | ||
| 38 | + y: 300, | ||
| 39 | + }, | ||
| 40 | + ], | ||
| 41 | + edges: [ | ||
| 42 | + { | ||
| 43 | + sourceNodeId: 'rect_3', | ||
| 44 | + targetNodeId: 'rect_2', | ||
| 45 | + type: 'custom-edge', | ||
| 46 | + text: '连线文本', | ||
| 47 | + }, | ||
| 48 | + { | ||
| 49 | + sourceNodeId: 'rect_5', | ||
| 50 | + targetNodeId: 'rect_4', | ||
| 51 | + type: 'bezier', | ||
| 52 | + }, | ||
| 53 | + { | ||
| 54 | + sourceNodeId: 'rect_5', | ||
| 55 | + targetNodeId: 'rect_9', | ||
| 56 | + type: 'line', | ||
| 57 | + }, | ||
| 58 | + ], | ||
| 59 | +}; | ||
| 60 | + | ||
| 61 | +export default data; |
src/views/adv-edge/animation/index.vue
0 → 100644
| 1 | +<!-- | ||
| 2 | + * @Date: 2025-03-10 16:52:35 | ||
| 3 | + * @LastEditors: hookehuyr hookehuyr@gmail.com | ||
| 4 | + * @LastEditTime: 2025-03-13 12:26:00 | ||
| 5 | + * @FilePath: /logic-flow2/src/views/adv-edge/animation/index.vue | ||
| 6 | + * @Description: 动画 | ||
| 7 | +--> | ||
| 8 | +<template> | ||
| 9 | + <div class="container"> | ||
| 10 | + <div ref="container" class="flow-container"></div> | ||
| 11 | + <button @click="edgeAnimation">动画</button> | ||
| 12 | + </div> | ||
| 13 | +</template> | ||
| 14 | + | ||
| 15 | +<script setup> | ||
| 16 | +import LogicFlow from "@logicflow/core"; | ||
| 17 | +import customEdge from "./customEdge"; | ||
| 18 | +import data from "./data"; | ||
| 19 | + | ||
| 20 | +const container = ref(null); | ||
| 21 | +let lf = null; | ||
| 22 | + | ||
| 23 | +onMounted(() => { | ||
| 24 | + lf = new LogicFlow({ | ||
| 25 | + container: container.value, | ||
| 26 | + grid: true, | ||
| 27 | + adjustEdgeStartAndEnd: true, // 开启两端的调整连线功能 | ||
| 28 | + edgeGenerator: (sourceNode) => { | ||
| 29 | + if (sourceNode.type === "circle") { | ||
| 30 | + return "line"; | ||
| 31 | + } | ||
| 32 | + }, | ||
| 33 | + }); | ||
| 34 | + | ||
| 35 | + lf.register(customEdge); | ||
| 36 | + lf.setDefaultEdgeType("custom-edge"); | ||
| 37 | + | ||
| 38 | + lf.render(data); | ||
| 39 | + lf.translateCenter(); | ||
| 40 | +}); | ||
| 41 | + | ||
| 42 | +const edgeAnimation = () => { | ||
| 43 | + const { edges } = lf?.getGraphRawData(); | ||
| 44 | + edges?.forEach(({ id }) => { | ||
| 45 | + lf?.openEdgeAnimation(id); | ||
| 46 | + }); | ||
| 47 | +}; | ||
| 48 | +</script> | ||
| 49 | + | ||
| 50 | +<style scoped> | ||
| 51 | +.container { | ||
| 52 | + width: 100vw; | ||
| 53 | + height: 100vh; | ||
| 54 | + display: flex; | ||
| 55 | + flex-direction: column; | ||
| 56 | +} | ||
| 57 | + | ||
| 58 | +.flow-container { | ||
| 59 | + flex: 1; | ||
| 60 | + width: 100%; | ||
| 61 | + height: 100%; | ||
| 62 | +} | ||
| 63 | +</style> |
| 1 | <!-- | 1 | <!-- |
| 2 | * @Date: 2025-03-10 14:37:31 | 2 | * @Date: 2025-03-10 14:37:31 |
| 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com | 3 | * @LastEditors: hookehuyr hookehuyr@gmail.com |
| 4 | - * @LastEditTime: 2025-03-12 21:27:39 | 4 | + * @LastEditTime: 2025-03-13 12:14:50 |
| 5 | * @FilePath: /logic-flow2/src/views/home.vue | 5 | * @FilePath: /logic-flow2/src/views/home.vue |
| 6 | * @Description: 文件描述 | 6 | * @Description: 文件描述 |
| 7 | --> | 7 | --> |
| ... | @@ -20,6 +20,7 @@ | ... | @@ -20,6 +20,7 @@ |
| 20 | <el-button type="primary" @click="goTo('theme')">theme</el-button> | 20 | <el-button type="primary" @click="goTo('theme')">theme</el-button> |
| 21 | <el-button type="primary" @click="goTo('adv-node-rule')">adv-node-rule</el-button> | 21 | <el-button type="primary" @click="goTo('adv-node-rule')">adv-node-rule</el-button> |
| 22 | <el-button type="primary" @click="goTo('adv-node-anchor')">adv-node-anchor</el-button> | 22 | <el-button type="primary" @click="goTo('adv-node-anchor')">adv-node-anchor</el-button> |
| 23 | + <el-button type="primary" @click="goTo('adv-edge-animation')">adv-edge-animation</el-button> | ||
| 23 | </template> | 24 | </template> |
| 24 | 25 | ||
| 25 | <script setup> | 26 | <script setup> | ... | ... |
-
Please register or login to post a comment