开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了。我们认为这样的经验是有必要记录下来的,因此就有了【技术博客】。

基于JsPlumb和JQuery-UI的流程图的保存和再生成

这篇技术博客基于软件工程课程的VisualPytorch之上,代码在一定程度上参考了https://www.cnblogs.com/sggx/p/3836432.html这篇博客。

VisualPytorch项目链接如下:VisualPytorch

前言-为什么要保存流程图

对于这样一个类流程图或者模型图,用户会有保存、查看以及再编辑的需求,仅仅提供让用户拖拽连线的功能、让用户每次都从头搭建是会严重影响用户体验的,因此需要能够保存模型图。

这篇博客主要用于提供思路,而非提供整套的解决方案,具体解决方案因人而异。

如何保存流程图

保存流程图是两方面的问题:

(1)选定合适的保存格式

(2)确保保存的信息足够来还原完整的图

在保存时,我采用的是将整个图分为两个数组保存入数据库中。图主要由模块(开始、reshape层)和连线两部分组成,因此我选择将模块保存为一个json,而连线保存为数组。

保存模块采用的主要方法

$("#canvas").find(".node").each(function (index, element) {
var id = $(element).attr('id');
nets[id] = {
"name": $(element).attr('name'),
"attribute": eval('(' + window.localStorage.getItem(id) + ')'),
"left": $(element).css('left'),
"top": $(element).css('top')
}
});

在画布中遍历所有的模块类,nets对象的标签为模块的id,而内容为需要保存的属性。需要注意的是,left与top属性必须保存,其相当于x,y坐标,用于还原时定位div的位置。

保存连线采用的主要方法

for (var i = 0; i < conn_list.length; i++) {
var source_id = conn_list[i]["sourceId"];
var target_id = conn_list[i]["targetId"];
var conn = {
"source": {
"id": source_id,
"anchor_position": conn_list[i]["endpoints"][0]["anchor"]["type"]
},
"target": {
"id": target_id,
"anchor_position": conn_list[i]["endpoints"][1]["anchor"]["type"]
}
};
nets_conn.push(conn);
}

连线保存需要注意两个地方,首先是conn_list的获得,即如何得到目前的所有连线,这里我调用了JsPlumb中现有的接口

conn_list = jsPlumb.getAllConnections()

另一个地方时anchor_position。这里涉及到了JsPlumb的部分,在连线的时候,只有有anchor的地方才可以连线,为了复原整个图,我们需要记录下anchor的位置。

如何复原流程图

如何将保存的数据从数据库中取出不应该是本博客的内容,不多赘述。先贴上完整代码

 var structure = eval('(' + net_work["structure"] + ')');
var nets = structure['nets'];
var nets_conn = structure['nets_conn'];
var static_val = structure['static'];
var drop_function = $("#canvas").droppable('option', 'drop');
var event;
jQuery.each(nets, function (id, val) { jsPlumb.ready(function () {
var ui = {
'offset': {
'left': parseInt(val['left'].split('px')) + $("#canvas").offset().left,
'top': parseInt(val['top'].split('px')) + $("#canvas").offset().top
},
'draggable': [{
"id": val['name'],
"innerHTML": $("#" + val['name'])[0].innerHTML
}],
'id': id
};
drop_function(event, ui);
});
window.localStorage.setItem(id, JSON.stringify(val['attribute']));
});
jQuery.each(nets_conn, function (id, val) {
jsPlumb.ready(function () {
jsPlumb.connect({
"source": val['source']['id'],
"target": val['target']['id'],
"anchors": [val['source']['anchor_position'], val['target']['anchor_position']],
"endpoint": ["Dot", {radius: 5}],
"paintStyle": {
stroke: "#fc2f49",
strokeWidth: 3, },
"maxConnections": -1,
"connector": ["Flowchart", {
stub: [40, 60],
gap: 5,
cornerRadius: 5,
alwaysRespectStubs: true
}],
"overlays": [["Arrow", {width: 10, length: 10, location: 1}]],
"connectionsDetachable": true,
})
});
});

代码看着很多,原理非常简单,就是把用户画图的操作再用js脚本做一遍。

放置模块

首先第一点,用户在拖拽div进入画布时,画布为droppable状态,会触发JQuery-UI 的drop事件。

$("#canvas").droppable({
scope: "ss",
drop: function (event, ui) {
.......
}
})

第一段代码中的

 var drop_function = $("#canvas").droppable('option', 'drop')

drop_function函数就对应了drop事件触发后执行的代码块。

如此一来便很容易理解,只要让每个被保存的模块去触发drop事件即可,参数ui用保存的属性来自己构造,详情参照代码。

重新连线

重新连线部分,直接调用JsPlumb的连线方法

jsPlumb.connect()

即可。

注意我们的anchor要选择之前保存的anchor。

【技术博客】基于JsPlumb和JQuery-UI的流程图的保存和再生成的更多相关文章

  1. [技术博客]基于动态继承类、WebDriver的浏览器兼容性测试框架搭建

    问题背景 观察使用selenium进行自动化测试的过程,我们可以将它概述为: 启动测试进程,在该进程中构建WebDriver 启动浏览器进程,将它与WebDriver建立连接 使用WebDriver向 ...

  2. 【技术博客】JWT的认证机制Django项目中应用

    开发组在开发过程中,都不可避免地遇到了一些困难或问题,但都最终想出办法克服了.我们认为这样的经验是有必要记录下来的,因此就有了[技术博客]. JWT的认证机制Django项目中应用 这篇技术博客基于软 ...

  3. 技术博客——微信小程序UI的设计与美化

    技术博客--微信小程序UI的设计与美化 在alpha阶段的开发过后,我们的小程序也上线了.看到自己努力之后的成果大家都很开心,但对比已有的表情包小程序,我们的界面还有很大的提升空间,许多的界面都是各个 ...

  4. 【转】【技术博客】Spark性能优化指南——高级篇

    http://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651745207&idx=1&sn=3d70d59cede236e ...

  5. [技术博客]使用CDN加快网站访问速度

    [技术博客]使用CDN加快网站访问速度 2s : most users are willing to wait 10s : the limit for keeping the user's atten ...

  6. [技术博客]采用Bootstrap框架进行排版布局

    [技术博客]采用Bootstrap框架进行排版布局 网页的前端框架有很多很多种,比如Bootstrap.Vue.Angular等等,在最开始其实并没有考虑到框架这回事,开始阅读往届代码时发现其部分采用 ...

  7. 【新版】Android技术博客精华汇总

    [新版]Android技术博客精华汇总(原文链接内持续更新) http://www.apkbus.com/thread-313856-1-1.html Kotlin Kotlin学习资料汇总 http ...

  8. [技术博客]海报图片生成——小程序canvas画布

    目录 背景介绍 canvas简介 代码实现 难点讲解 圆角矩形裁剪失败之PS的妙用 编码不要过硬 对过长的文字进行截取 真机首次生成时字体不对 drawImage只能使用本地图片 背景介绍 目标:利用 ...

  9. [技术博客] Android 自动化测试

    [技术博客] Android 自动化测试 安卓自动化测试工具与平台的搭建 类似于网页端自动化,安卓测试的自动化也主要是针对控件的自动化.其原理就是通过python(其他语言) 的脚本来代替我们手动完成 ...

随机推荐

  1. 91.用js遍历原生json数据

    <!doctype html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  2. Python基础(四)--数据类型、字符编码、文件处理

    一.数据类型 1. 数据类型 数字(整形,长整形,浮点型,复数) 字符串 字节串(字节bytes类型) 列表 元组 字典 集合 2. 按照以下几个点展开数据类型的学习 #=============== ...

  3. cad快捷键与命令大全

    一入绘图深似海,从此各种快捷键就要不分昼夜在脑海,忘记了哪一个,对于效率来说都是一个考验. 快捷键用处怎么大,那么的实用,需要背诵哪些呢?史上最全快捷键汇总,大神都在使用快捷键操作,这里给你来一个大汇 ...

  4. Docker 修改容器内的时区

    利用docker发布服务,发现 程序用获取的系统时间比正常时间晚了8个小时 进入容器 docker exec -it /bin/sh 查询时间 date -R 发现时区为0时区 解决思路 1.复制相应 ...

  5. 使用salt-stack指定IP添加系统用户为root的权限

    指定多台要授权的用户,指定root权限 salt -L '192.168.3.212' cmd.run 'useradd fengniao -u 2000' salt -L '192.168.3.21 ...

  6. PAT甲级1013题解——并查集+路径压缩

    题目分析: 本题初步浏览题目就知道是并查集的模板题,数据输入范围N为1~1000,则M的范围为0~1000^2,通过结构体记录每一对连线的关系,p[]数组记录每个节点的跟,对于k次查询,每次都要重新维 ...

  7. 分布式中的分库分表之后,ID 主键如何处理?

    面试题 分库分表之后,id 主键如何处理?(唯一性,排序等) 面试官心理分析 其实这是分库分表之后你必然要面对的一个问题,就是 id 咋生成?因为要是分成多个表之后,每个表都是从 1 开始累加,那肯定 ...

  8. 实验十四:团队项目评审&课程学习总结

    项目 内容 作业所属课程 所属课程 作业要求 作业要求 课程学习目标 (1)掌握软件项目评审会流程:(2)反思总结课程学习内容 任务一:团队项目审核已完成.项目验收过程意见表已上交. 任务二:课程学习 ...

  9. 《团队名称》第八次团队作业:Alpha冲刺day3

    项目 内容 这个作业属于哪个课程 2016计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8-软件测试与ALPHA冲刺 团队名称 快活帮 作业学习目标 (1)掌握 ...

  10. rhel6.2配置在线yum源

    由于 redhat的yum在线更新是收费的,如果没有注册的话不能使用,如果要使用,需将redhat的yum卸载后,重启安装,再配置其他源. 本文包括配置本地源及第三方源.第三方源包括:网易,epel, ...