如何自己实现一个丝滑的流程图绘制工具(七)bpmn-js 批量删除、复制节点

背景

希望实现批量删除和复制节点,因为bpmn-js是canvas画的,所以不能像平时页面上的复制一样直接选择范围,会变成移动画布。

思路是:

绘制一个选择的效果框,这样才可以看出来选的节点有哪些。
在这里插入图片描述
上面的选中范围框效果也是用canvas画出来的
因为bpmn-js对鼠标直接选取范围进行了拦截。所以我加了一个辅助按键进行选择

一、 以下是绘制选择框范围的代码:
     * @param {MouseEvent} e*/onMousedown(e) {this.removeActiveClass()this.batchSelectedList = []   if (!e.metaKey && !e.altKey && !e.ctrlKey) {return}e.target.addEventListener('mouseup', this.onMouseup)if (!this.rectSelect) {const rect = this.$refs.canvas.getBoundingClientRect()this.startX = e.clientX - rect.leftthis.startY = e.clientY - rect.topconst g = this.$el.getElementsByTagName('svg')[1]this.rectSelect = document.createElementNS('http://www.w3.org/2000/svg', 'rect')this.rectSelect.setAttribute('fill', 'rgba(93,148,231,0.2)')this.rectSelect.setAttribute('stroke-width', '2px')this.rectSelect.setAttribute('stroke', 'rgba(93,148,231,0.2)')g.append(this.rectSelect)}},/*** @param {MouseEvent} e*/onMousemove(e) {if (!this.enableBatchSelect) returnthis.currentMouseEvent = eif (!this.rectSelect) {return}e.stopPropagation()const canvasRect = this.$refs.canvas.getBoundingClientRect()const w = e.clientX - this.startX - canvasRect.leftconst h = e.clientY - this.startY - canvasRect.topconst x = this.startXconst y = this.startYthis.rectSelect.setAttribute('x', w < 0 ? e.clientX - canvasRect.left : this.startX)this.rectSelect.setAttribute('y', h < 0 ? e.clientY - canvasRect.top : this.startY)this.rectSelect.setAttribute('width', `${Math.abs(w)}`)this.rectSelect.setAttribute('height', `${Math.abs(h)}`)const elementRegistry = this.bpmnModeler.get('elementRegistry')const canvas = this.bpmnModeler.get('canvas')const box = canvas.viewbox()const elementList = elementRegistry.getAll()const nodeList = elementList.filter(f => f.type === 'bpmn:Task')this.connectLineList = elementList.filter(f => f.type === 'bpmn:SequenceFlow')const boxX = box.xconst boxY = box.ythis.batchSelectedList = nodeList.filter(item => {const x1 = -(boxX - item.x) * box.scaleconst y1 = -(boxY - item.y) * box.scaleconst pointers = [{ x: x, y: y },{ x: x + w, y: y },{ x: x + w, y: y + h },{ x: x, y: y + h }]return inRect(x1, y1, pointers)})},onMouseup(e) {if (this.rectSelect) {this.rectSelect.remove()}this.rectSelect = nulle.target.removeEventListener('mouseup', this.onMouseup)const elementRegistry = this.bpmnModeler.get('elementRegistry')this.batchSelectedList.forEach(item => {const id = item.idconst el = elementRegistry._elements[id]?.gfxif (el) {el.classList.add('batch-selected')this.activeIdList.push(id)}})},removeActiveClass() {const elementRegistry = this.bpmnModeler.get('elementRegistry')this.activeIdList.forEach(id => {const el = elementRegistry._elements[id]?.gfxif (el) {el.classList.remove('batch-selected')}})this.activeIdList = []}
<style>
.djs-element.batch-selected .djs-outline {stroke: rgb(54, 147, 255) !important;visibility: visible !important;
}
</style>
二、然后是把选中的数据放入剪贴板
 async onCopy(isShowMessage = true) {if (this.copyData.length === 0) returntry {await navigator.clipboard.writeText(JSON.stringify(copyData))isShowMessage && this.$message.success(`已复制${copyData.length}个节点`)} catch (e) {this.$message.error('写入剪切板失败')console.error(e)}},
三、粘贴的操作
    /*** 粘贴* @param {KeyboardEvent} e*/async onPaste(e) {const text = await navigator.clipboard.readText()try {const copyData = JSON.parse(text)const canvas = this.bpmnModeler.get('canvas')const box = canvas.viewbox()const elementFactory = this.bpmnModeler.get('elementFactory')const elementRegistry = this.bpmnModeler.get('elementRegistry')const parent = elementRegistry.find(el => el.type === 'bpmn:Process')const modeling = this.bpmnModeler.get('modeling')if (!copyData.nodes.length) returnconst rect = this.$el.getBoundingClientRect()const mouseX = this.currentMouseEvent.clientX - rect.xconst mouseY = this.currentMouseEvent.clientY - rect.y// 计算第0个元素和当前鼠标所在位置的差值const first = copyData.nodes[0]const diffX = first.x - mouseXconst diffY = first.y - mouseYcopyData.nodes.forEach(item => {const x = item.x + box.x - diffXconst y = item.y + box.y - diffYconst shape = elementFactory.createShape({type: 'bpmn:Task',x: x,y: y})modeling.createShape(shape, { x: x, y: y }, parent)shape.data = item.dataif (item.data.name) {this.createLabel(shape, item.data.name)}this.pateShapeMap[item.id] = shape})copyData.lines.forEach(line => {const startShape = this.pateShapeMap[line.sourceId]const targetShape = this.pateShapeMap[line.targetId]if (startShape && targetShape) {const lines = modeling.connect(startShape, targetShape)lines.data = line.dataif (lines.data.name) {this.createLabel(lines, lines.data.name)}this.pateLineMap[lines.id] = lines}})} catch (e) {console.error(e)}},

在这里插入图片描述

以上就是批量复制的步骤

批量删除
在这里插入图片描述

  batchDelete() {const bpmnModeling = this.bpmnModeler.get('modeling')this.activeIdList.forEach(nodeId => {const element = this.bpmnModeler.get('elementRegistry').get(nodeId)bpmnModeling.removeElements([element])})  },

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

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

相关文章

K8S最新版本集群部署(v1.28) + 容器引擎Docker部署(下)

温故知新 &#x1f4da;第三章 Kubernetes各组件部署&#x1f4d7;安装kubectl&#xff08;可直接跳转到安装kubeadm章节&#xff0c;直接全部安装了&#xff09;&#x1f4d5;下载kubectl安装包&#x1f4d5;执行kubectl安装&#x1f4d5;验证kubectl &#x1f4d7;安装kubead…

Go死码消除

概念: 死码消除(dead code elimination, DCE) 是一种编译器优化技术, 作用是在编译阶段去掉对程序运行结果没有任何影响的代码 和 逃逸分析[1],内联优化[2]并称为 Go编译器执行的三个重要优化 效果: 对于 const.go代码如下: package mainimport "fmt"func max(a, b i…

wireshark过滤器的使用

目录 wiresharkwireshark的基本使用wireshark过滤器的区别 抓包案例 wireshark wireshark的基本使用 抓包采用 wireshark&#xff0c;提取特征时&#xff0c;要对 session 进行过滤&#xff0c;找到关键的stream&#xff0c;这里总结了 wireshark 过滤的基本语法&#xff0c;…

芯科科技宣布推出下一代暨第三代无线开发平台,打造更智能、更高效的物联网

第三代平台中的人工智能/机器学习引擎可将性能提升100倍以上 Simplicity Studio 6软件开发工具包通过新的开发环境将开发人员带向第三代平台 中国&#xff0c;北京 - 2023年8月22日 – 致力于以安全、智能无线连接技术&#xff0c;建立更互联世界的全球领导厂商Silicon Labs&…

java定位问题工具

一、使用 JDK 自带工具查看 JVM 情况 在我的机器上运行 ls 命令&#xff0c;可以看到 JDK 8 提供了非常多的工具或程序&#xff1a; 接下来&#xff0c;我会与你介绍些常用的监控工具。你也可以先通过下面这张图了解下各种工具的基本作用&#xff1a; 为了测试这些工具&#x…

从LeakCanary看内存快照解析

在从LeakCanary看内存快照生成一节中&#xff0c;我们已经了解了hprof的生成&#xff0c;并且将生成的hprof文件通过Android Studio进行解析&#xff0c;确实发现了内存泄漏对象MainActivity&#xff0c;但是在实际开发中&#xff0c;要求开发者自己去手动pull hprof文件进行解…

5.基于多能互补的热电联供型微网优化运行

MATLAB代码链接&#xff1a;基于多能互补的热电联供型微网优化运行 MATLAB代码&#xff1a;基于多能互补的热电联供型微网优化运行 关键词&#xff1a;多能互补 综合需求响应 热电联产 微网 优化调度 参考文档&#xff1a;《基于多能互补的热电联供型微网优化运行》基本完全…

链表(详解)

一、链表 1.1、什么是链表 1、链表是物理存储单元上非连续的、非顺序的存储结构&#xff0c;数据元素的逻辑顺序是通过链表的指针地址实现&#xff0c;有一系列结点&#xff08;地址&#xff09;组成&#xff0c;结点可动态的生成。 2、结点包括两个部分&#xff1a;&#x…

OLED透明屏显示技术:未来显示科技的领航者

OLED透明屏显示技术是一种创新性的显示技术&#xff0c;它的特殊性质使其成为未来显示科技的领航者。 OLED透明屏具有高对比度、快速响应时间、广视角和低功耗等优势&#xff0c;同时&#xff0c;其透明度、柔性和薄型设计使其成为创新设计的理想选择。 本文将深入探讨OLED透…

NSS [NUSTCTF 2022 新生赛]Ezjava1

NSS [NUSTCTF 2022 新生赛]Ezjava1 题目描述&#xff1a;你能获取flag{1}吗 开题&#xff0c;一眼java web中的index.jsp。 默认index.jsp中的body内容是$END$ 附件jar包导入IDEA&#xff0c;会自动反编译。看看源码。 附件结构大致如此。主要看classes.com.joe1sn中的代码就…

MyBatisx代码生成

MyBatisx代码生成 1.创建数据库表 CREATE TABLE sys_good (good_id int(11) NOT NULL,good_name varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,good_desc varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,PRIMARY KEY (good_id) ) ENGINEInnoDB DEFAULT CHA…

【C++设计模式】用动画片《少年骇客》(Ben10)来解释策略模式

2023年8月25日&#xff0c;周五上午 今天上午学习设计模式中的策略模式时&#xff0c;发现这个有点像很多卡通片里面的变身器... 2023年8月26日&#xff0c;周六上午 更新&#xff1a;和简单工厂模式结合 目录 用策略模式写主角的变身器 使用策略模式的好处和简单工厂模式结…

手写实现call() apply() bind()函数,附有详细注释,包含this指向、arguments讲解

手写实现call() apply() bind()函数是很经典的问题&#xff0c;但是能掰扯清楚的文章确实不算多&#xff0c;于是笔者才决定写下本文&#xff0c;希望能给读者带来一些启发&#xff0c;如有错误欢迎指正。 目录 补充知识 函数中的this指向 类数组对象arguments call() 原理…

每日三题 1448统计二叉树中好节点的个数 100相同的树 101对称二叉树

1448 题目 给你一棵根为 root 的二叉树&#xff0c;请你返回二叉树中好节点的数目。 「好节点」X 定义为&#xff1a;从根到该节点 X 所经过的节点中&#xff0c;没有任何节点的值大于 X 的值。 示例 1&#xff1a; 输入&#xff1a;root [3,1,4,3,null,1,5] 输出&#xff…

弯道超车必做好题集锦三(C语言选择题)

前言&#xff1a; 编程想要学的好&#xff0c;刷题少不了&#xff0c;我们不仅要多刷题&#xff0c;还要刷好题&#xff01;为此我开启了一个弯道超车必做好题锦集的系列&#xff0c;每篇大约10题左右。此为第三篇选择题篇&#xff0c;该系列会不定期更新&#xff0c;后续还会…

MongoDB实验——在Java应用程序中操作 MongoDB 数据

在Java应用程序中操作 MongoDB 数据 1. 启动MongoDB Shell 2. 切换到admin数据库&#xff0c;使用root账户 3.开启Eclipse&#xff0c;创建Java Project项目&#xff0c;命名为MongoJava File --> New --> Java Project 4.在MongoJava项目下新建包&#xff0c;包名为mo…

《Go 语言第一课》课程学习笔记(十三)

方法 认识 Go 方法 Go 语言从设计伊始&#xff0c;就不支持经典的面向对象语法元素&#xff0c;比如类、对象、继承&#xff0c;等等&#xff0c;但 Go 语言仍保留了名为“方法&#xff08;method&#xff09;”的语法元素。当然&#xff0c;Go 语言中的方法和面向对象中的方…

C++------map和set的使用

文章目录 关联式容器键值对树型结构的关联式容器set的介绍map的介绍 关联式容器 什么是关联式容器&#xff1f;它与序列式容器有什么区别&#xff1f; 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是<key&#xff0c;value>结…

【数据结构】手撕顺序表

一&#xff0c;概念及结构 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储&#xff1b; 在数组上完成数据的增删查改。 1&#xff0c; 静态顺序表&#xff1a;使用定长数组存储元素。 2.&#xff0c;动态顺序表&#xff1…

系统架构设计高级技能 · 云原生架构设计理论与实践

系列文章目录 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;二&#xff09;【系统架构设计师】 系统架构设计高级技能 软件可靠性分析与设计…