可拖拽流程图组件开发

效果

在这里插入图片描述

说在前面

流程图在技术领域是一种常见的可视化工具,用于展示系统、应用或业务流程的各个步骤以及它们之间的关系。它们可以帮助开发人员和项目团队更好地理解和规划复杂的流程,从而提高工作效率和准确性。但是,传统的静态流程图有时无法满足用户的需求,因此实现可拖拽的流程图组件成为了一个重要的需求。

实现可拖拽的流程图组件的目的和意义是为了提供一种交互性更强、用户体验更好的流程图展示方式。通过该组件,用户可以轻松地拖拽节点进行重新排序,自由调整流程图的结构和布局,从而更好地满足项目需求并提高工作效率。

组件设计

首先需要设计好配置参数,然后就是讲配置参数融入到样式的设计处理上,最后是实现组件拖动并实时展示效果。

参数

整体参数
参数描述
title标题(String)
dragAble是否可拖拽(Boolean)
width图标最小宽度(number)
radius是否圆角(Boolean)
data流程项(Array)
data流程项参数

结构如下

[{icon:require('@/assets/logo.png'),//图标text:'准备'//文字},{icon:require('@/assets/1.png'),text:'开始'},
]

功能

拖拽事件监听

通过监听鼠标的按下、移动和抬起等事件,实现节点的拖拽功能。

if (this.chartData.dragAble) {document.getElementById("flow-chart").addEventListener("mouseup", this.handleMouseup);document.getElementById("flow-chart").addEventListener("mouseover", this.handleMouseover);document.getElementById("flow-chart").addEventListener("touchend", this.handleMouseup);document.getElementById("flow-chart").addEventListener("touchmove", this.handleMouseover);
}
阻止默认事件

为了确保拖拽功能正常运作,需要在拖拽过程中阻止浏览器默认的拖拽行为。

//阻止默认事件
preventEvent() {document.getElementById("flow-chart").ondragstart = function () {return false;};document.getElementById("flow-chart").onselectstart = function () {return false;};
},
初始化样式和数据

在组件加载时,需要初始化节点的样式和位置,以及计算每个节点的宽度和每行显示的数量。

//初始化样式变量
initStyle() {let chartContent = this.$refs.chartContent;let width = chartContent.offsetWidth - 40;let itemWidth = Math.max(20, Math.floor(width / 7));if (this.chartData.width) {itemWidth = this.chartData.width;}this.itemWidth = itemWidth;this.itemNum = Math.floor(width / (itemWidth + itemWidth / 5));
},
//初始化数据
initData() {let data = this.vChartDataList;let res = [],flag = true,temp = [];for (let i = 1; i <= data.length; i++) {data[i - 1].id = "item" + "-" + res.length + "-" + (i - 1);if (flag) temp.push(data[i - 1]);else temp.unshift(data[i - 1]);if (i % this.itemNum == 0 || i == data.length) {res.push([...temp]);temp = [];flag = !flag;}}this.chartDataList = res;
},
//重组class
getClass(res, str) {if (this.chartData[str]) res += " " + str;return res;
},
//重组行样式
getColumnStyle(index) {let res = {};if (index < this.chartDataList.lenth - 1 || index % 2 == 0)return this.styleConcat(res);res["margin-left"] = "auto";res["margin-right"] = -this.itemWidth / 5 + "px;";return this.styleConcat(res);
},
//重组每个item的样式
getItemStyle(item = "") {let res = {};if (item != "") {if (item.opacity) {res.opacity = item.opacity;}return this.styleConcat(res);}res.width = this.itemWidth + "px;";res["margin-right"] = this.itemWidth / 5 + "px;";return this.styleConcat(res);
},
//重组每个item的icon的样式
getIconStyle(str) {let res = {};res.width = this.itemWidth - 5 + "px;";res.height = this.itemWidth - 5 + "px";if (str == "text") {res["line-height"] = this.itemWidth - 5 + "px";res["font-size"] = "large";res["border"] = "1px solid blue";res["background-color"] = "skyblue";}return this.styleConcat(res);
},
//获取连接线样式
getLineStyle(index, index1, flag) {if (index1 == this.chartDataList.length - 1 &&index == this.chartDataList[index1].length - 1)return "";let res = {};res["border-top"] = "1px solid black";res.width = this.itemWidth / 3 + "px";if (flag == "right")res["margin-right"] = -this.itemWidth / 3 + "px;";else {res["margin-left"] = -this.itemWidth / 3 + "px;";res["border-left"] = "1px solid black";}res["margin-top"] = this.itemWidth / 2 + "px;";if (index == this.chartDataList[0].length - 1 &&index1 < this.chartDataList.length - 1) {if (index1 % 2 == 0) {res["border-right"] = "1px solid black";}}if (index1 % 2 == 1) {if (index == this.chartDataList[index1].length - 1) return "";}return this.styleConcat(res);
},
//json变量转换为style字符串
styleConcat(obj) {let res = "";for (let k in obj) {res += k + ":" + obj[k] + ";";}return res;
},
处理鼠标抬起事件

当鼠标抬起时,将拖拽的节点插入到新的位置,并更新节点的样式和位置。

//鼠标抬起时
handleMouseup(event) {const chartContent = document.getElementById("chartContent");if (this.vChartDataList[this.oldInd])this.vChartDataList[this.oldInd].opacity = 1;chartContent.style.border = "none";this.operateDom = null;this.operateDomNum = null;this.oldInd = null;
},
处理鼠标移动事件

在拖拽过程中,根据鼠标的位置计算节点的新样式和位置,实现拖拽时的效果。

handleMouseover(event) {if (this.vChartDataList.length < this.chartData.data.length) {this.vChartDataList.unshift({ ...this.chartData.data[0] });}if (this.operateDom != null) {const w = this.operateDom.offsetWidth,h = this.operateDom.offsetHeight;let x = event.pageX,y = event.pageY;this.operateDom.style.position = "fixed";this.operateDom.style.opacity = "0.5";this.operateDom.style.left = x - w / 2 - window.scrollX + "px";this.operateDom.style.top = y - h / 2 - window.scrollY + "px";let { tx, ty } = this.getItemCoords(x, y);let oldInd = this.oldInd;if (oldInd >= 0) {this.vChartDataList.splice(oldInd, 1);this.initData();}let nty =parseInt(ty) % 2 == 0? parseInt(tx): this.itemNum - parseInt(tx);nty = Math.min(nty, this.itemNum);nty = Math.max(nty, 0);oldInd = parseInt(ty) * this.itemNum + nty;oldInd = Math.min(this.chartData.data.length - 1, oldInd);oldInd = Math.max(0, oldInd);this.oldInd = oldInd;if (oldInd < 0) return;this.vChartDataList.splice(oldInd, 0, { ...this.selectedItem });this.initData();}
},
//获取当前移动到的坐标
getItemCoords(x, y) {let d = document.getElementById("chartContent");let left = d.offsetLeft;let top = d.offsetTop;(x = x - left), (y = y - top);let itemNum = this.itemNum;let w = d.offsetWidth;let h = d.offsetHeight;let moveDiv = document.getElementById("moveDiv");let th = moveDiv.offsetHeight;w = Math.ceil(w / itemNum);(x = Math.floor(x / w)), (y = Math.floor(y / th));return { tx: x, ty: y };
},

源码

Gitee地址:https://gitee.com/zheng_yongtao/jyeontu-component-warehouse

预览地址

组件文档:http://jyeontu.xyz/jvuewheel/#/flowChartView

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/313275.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《PCI Express体系结构导读》随记 —— 第I篇 第2章 PCI总线的桥与配置(1)

前言中曾提到&#xff1a;本章重点介绍PCI桥。 在PCI体系结构中含有两类桥&#xff1a;一类是HOST主桥&#xff1b;另一类是PCI桥。在每一个PCI设备中&#xff08;包括PCI桥&#xff09;&#xff0c;都含有一个配置空间。这个配置空间由HOST主桥管理&#xff0c;而PCI桥可以转…

探索 CodeWave低代码技术的魅力与应用

目录 前言1 低代码平台2 CodeWave简介3 CodeWave 的独特之处3.1 高保真还原交互视觉需求3.2 擅长复杂应用开发3.3 支持应用导出&独立部署3.4 金融级安全要求3.5 可集成性高3.6 可拓展性强 4 平台架构和核心功能4.1 数据模型设计4.2 页面设计4.3 逻辑设计4.4 流程设计4.5 接…

fanout(扇出模型)

在广播的流程下&#xff0c;消息发送的流程如下&#xff1a; 可以有多个消费者。 每个消费者有自己的queue(队列)。 每个队列都要绑定到Exchange(交换机)。 生产者发送的消息&#xff0c;只能发送到交换机&#xff0c;交换机来决定要发给哪个队列&#xff0c;生产者也无法决…

ROS安装PR2

一、PR2介绍 PR2是Willow Garage公司设计的机器人平台&#xff0c;也是目前科研领域经常用到的机器人之一。PR2有两条手臂&#xff0c;每条手臂七个关节&#xff0c;手臂末端是一个可以张合的夹爪&#xff1b;PR2依靠底部的四个轮子移动&#xff0c;在头部、胸部、肘部、夹爪上…

win11 电脑睡眠功能失效了如何修复 win11 禁止鼠标唤醒

1、win11睡眠不管用怎么办&#xff0c;win11电脑睡眠功能失效了如何修复 在win11系统中拥有许多令人激动的新功能和改进&#xff0c;有些用户在使用win11电脑时可能会遇到一个问题&#xff1a;睡眠模式不起作用。当他们尝试将计算机置于睡眠状态时&#xff0c;却发现系统无法进…

使用WAZUH检测LD_PRELAOD劫持、SQL注入、主动响应防御

目录 1、检查后门 使用工具检测后门 1.chkrootkit 2.rkhunter 手动检查文件 检查ld.so.preload文件 2、检测LD_PRELOAD ubuntu配置 wazuh配置 3、检测SQL注入 ubuntu配置 攻击模拟 4、主动响应 wauzh的安装以及设置代理可以参考本篇&#xff1a;WAZUH的安装、设置…

视频合并软件,重塑你的创意世界

在数字化的世界里&#xff0c;视频已经成为了我们表达自我、传递信息的重要方式。而合并视频&#xff0c;更是将这种表达推向了一个新的高度。通过简单的操作&#xff0c;我们不仅能够将不同的视频完美地融合在一起&#xff0c;更能赋予它们全新的含义。 所需工具&#xff1a;…

第四部分 一维连续型随机变量

目录 温馨提示&#xff1a; 已知fx(X)求概率 方法&#xff1a; 例1 例2 求fx(X)中的未知数 方法&#xff1a; 例3 已知 fx(X)求F 方法&#xff1a; 例4 求F中的未知数 方法&#xff1a; 例5 已知F求f 方法&#xff1a; 例6 已知f求f 方法&#xff1a; 普通求法&#xff1a; 公…

第二十六周:学习笔记

第二十六周&#xff1a;学习笔记 摘要Abstract全卷积网络 FCN1. CNN 与 FCN2. 全连接层 --> 成卷积层3. FCN的缺点 摘要 全卷积神经网络&#xff08;Fully Convolutional Network&#xff0c;FCN&#xff09;是一种用于图像分割和语义分割任务的深度学习模型。与传统的卷积…

微信小程序发送模板消息-详解【有图】

前言 在发送模板消息之前我们要首先搞清楚微信小程序的逻辑是什么&#xff0c;这只是前端的一个demo实现&#xff0c;建议大家在后端处理&#xff0c;前端具体实现&#xff1a;如下图 1.获取小程序Id和密钥 我们注册完微信小程序后&#xff0c;可以在开发设置中看到以下内容&a…

C语言之分支与循环【附6个练习】

文章目录 前言一、什么是语句&#xff1f;1.1 表达式语句1.2 函数调用语句1.3 控制语句1.4 复合语句1.5 空语句 二、分支语句&#xff08;选择结构&#xff09;2.1 if语句2.1.1 悬空else2.1.2 练习&#xff08;1. 判断一个数是否为奇数 2. 输出1-100之间的奇数&#xff09; 2.2…

Vue中目录以及文件内容简单分析

src文件下目录分析&#xff1a; App.vue文件中内容&#xff1a; vue文件中基本的三个结构&#xff0c;template&#xff08;结构&#xff09;、script&#xff08;行为&#xff09; 、style&#xff08;样式&#xff09;。 <template><!-- html结构 --><div cl…