最近项目上需要用流程图来做问题定界分析,之前有同事用jsPlumb做过,但是阅读代码后觉得比较麻烦,所以自己又找了一圈,找到一个叫Dagre-D3的开源类库,画出来的效果如下图,Dagre-D3最大的优点就是可以实现自动布局,你只需要put数据就可以了,但是缺点就是自动布局后的连线会比较乱,而且连线不是横平竖直的,对于流程图不复杂的还好,稍微复杂点画出来的连线就没法看。最后还是被pass了。

jsPlumb地址:https://jsplumbtoolkit.com

Dagre-D3 Git地址:https://github.com/cpettitt/dagre-d3

  后面经过一番百度,最终决定用JointJS,官网:www.jointjs.com,相比Dagre-D3和jsPlumb,JointJS的API很详细,代码量少,连接线有多种选择,封装了多种常用的形状,而且能画的图很多,官方也给了一些demo可以参考。下面是我用JointJS画出来的流程图:

依赖:在官网的下载页面都能找到

<link rel="stylesheet" type="text/css" href="joint.css" />
<script src="jquery.min.js"></script>
<script src="lodash.min.js"></script>
<script src="backbone-min.js"></script>
<script src="joint.js"></script>

我的demo里还引用了bootstrap的依赖用来显示模态框

html代码

<body>
<div id="paper" class="paper"></div> <div class="modal fade searchpanel" id="detailModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="modalTitle">详细信息</h4>
</div>
<div class="modal-body"> </div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
</div>
</div>
</div>
</div>
</body>

js代码

首先是定义画板和画布,这里重写了ElementView和LinkView,目的是为了让画出来的流程图不能被删除和编辑

    var graph = new joint.dia.Graph();

    var ElementView = joint.dia.ElementView.extend({
pointerdown: function () {
this._click = true;
joint.dia.ElementView.prototype.pointerdown.apply(this, arguments);
},
pointermove: function(evt, x, y) {
this._click = false;
joint.dia.ElementView.prototype.pointermove.apply(this, arguments);
},
pointerup: function (evt, x, y) {
if (this._click) {
// triggers an event on the paper and the element itself
this.notify('cell:click', evt, x, y);
} else {
joint.dia.ElementView.prototype.pointerup.apply(this, arguments);
}
}
});
var LinkView = joint.dia.LinkView.extend({
addVertex: function(evt, x, y) {},
removeVertex: function(endType) {},
pointerdown:function(evt, x, y) {}
}); //定义画布
var paper = new joint.dia.Paper({
el: $('#paper'),
width: 1200,
height: 600,
gridSize: 1,
model: graph,
elementView: ElementView,
linkView:LinkView
});
//paper.$el.css('pointer-events', 'none')//去除默认样式,使所有事件不可用

然后我写了两个函数分别用来创建形状和连线,这样写可以减少代码量,官方的demo也大都是这样写的

    //定义形状
var state = function(x, y, shape, background, text){
var cell;
if(shape==="rect"){
cell = new joint.shapes.basic.Rect({
position: { x: x, y: y },//坐标
size: { width: 140, height: 40 },//宽高
attrs: {
rect: {
fill: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: background },//渐变开始
{ offset: '100%', color: '#fe8550' }//渐变结束
],
attrs: { x1: '0%', y1: '0%', x2: '0%', y2: '100%' }
},
stroke: background,//边框颜色
'stroke-width': 1//边框大小
},
text: { text: text } //显示文字
}
});
} else if(shape==="ellipse"){
cell = new joint.shapes.basic.Ellipse({
position: { x: x, y: y },//坐标
size: { width: 140, height: 40 },//宽高
attrs: {
ellipse: {
fill: {
type: 'linearGradient',
stops: [
{ offset: '0%', color: background },//渐变开始
{ offset: '100%', color: '#FFFFFF' }//渐变结束
],
attrs: { x1: '0%', y1: '0%', x2: '0%', y2: '100%' }
},
stroke: background,//边框颜色
'stroke-width': 1//边框大小
},
text: { text: text } //显示文字
}
});
}
graph.addCell(cell);
return cell;
}; //定义连线
function link(source, target, label){
var cell = new joint.dia.Link({
source: { id: source.id },
target: { id: target.id },
labels: [{ position: 0.5, attrs: { text: { text: label || '', 'font-weight': 'bold' } } }],
router: { name: 'manhattan' },//设置连线弯曲样式 manhattan直角
attrs: {
'.connection': {
stroke: '#333333',//连线颜色
'stroke-width': 2//连线粗细
},
'.marker-target': {
fill: '#333333',//箭头颜色
d: 'M 10 0 L 0 5 L 10 10 z'//箭头样式
}
}
});
graph.addCell(cell);
return cell;
}

最后就是我们实际的业务代码了,这里我们可以整理一下数据结构,把数据定义成json格式,然后写一个函数通过json直接生成流程图,当然坐标需要寻找规律自己计算一下

    //创建元素
var start = state(500,100,"ellipse","#00FFFF", "视频播放成功率");
var state1 = state(500,200,"rect","#f7a07b", "GET响应成功率");
var state2 = state(400,300,"rect","#f7a07b", "HTTP错误码分析");
var state3 = state(600,300,"rect","#f7a07b", joint.util.breakText("TCP异常和其他原因",{width:80}));
var state4 = state(400,400,"rect","#f7a07b", "4XX、5XX分析");
var state5 = state(600,400,"rect","#f7a07b", "接口以上分析");
var state6 = state(750,400,"rect","#f7a07b", "接口以下分析"); //创建连线
link(start, state1, "");
link(state1, state2, "≥70%");
link(state1, state3, "<70%");
link(state2, state4, "");
link(state3, state5, "是");
link(state3, state6, "否"); //给所有元素添加点击事件
paper.on('cell:click', function (e) {
$("#detailModal .modal-body").html("");
var arr = $("#"+e.id+" tspan");
if(arr.length===1){
$("#detailModal .modal-body").append($(arr).html());
$("#detailModal").modal();
} else{
var tmp="";
$.each(arr, function(k,v){
tmp+=$(v).html();
});
$("#detailModal .modal-body").append(tmp);
$("#detailModal").modal();
} });

后面是给每个元素(不包含连线)添加了一个点击事件,弹出一个模态框,显示当前点击的内容。

[原]JointJS流程图的更多相关文章

  1. JointJS绘制流程图

    摘要: JointJS是一个javascript图表库.你可以使用它制作静态或者动态的图表.关系表.流程图. 效果图:

  2. 【原】画流程图工具visio使用技巧汇总

    最近写论文需要画不少流程图,有两种选择,一是word, 二是visio.原先一直用word画,效果也还可以,但是每个部件画完后为了便于适应排版变动,需要将需要的模块按下ctrl逐个点击选中后进行组合. ...

  3. 一位资深开发的个人经历 【转自百度贴吧 java吧 原标题 4年java 3年产品 现在又开始做android了】

    楼主2007年从一家天津的三流大学毕业.毕业前报了一个职位培训,毕业后可以推荐工作.因为推荐的公司都是北京的,所以就来北京了. 找了一个月工作,没有找到要我的,就在出租屋里宅了起来,打着考研的旗号,又 ...

  4. 【原】http缓存与cdn相关技术

    摘要:最近要做这个主题的组内分享,所以准备了一个星期,查了比较多的资料.准备的过程虽然很烦很耗时间,不过因为需要查很多的资料,因此整个过程下来,对这方面的知识影响更加深刻.来来来,接下来总结总结 一 ...

  5. 使用jsPlumb制作流程图设计器

    jsPlumb是一个比较强大的绘图组件,它提供了一种方法,主要用于连接网页上的元素.在现代浏览器中,它使用SVG或者Canvas技术,而对于IE8以下(含IE8)的古董浏览器,则使用VML技术. 项目 ...

  6. 用HTML5构建一个流程图绘制工具

    在我们的开发工程中经常会使用到各种图,所谓的图就是由节点和节点之间的连接所形成的系统,数学上专门有一个分支叫图论(Graph Theroy).利用图我们可以做很多工具,比如思维导图,流程图,状态机,组 ...

  7. 动态流程图关于jointJs的使用

    这段时间由于业务需要,需要展现动态的流程图.具体实现效果如图所示: jointJS中的线条以及框都是依赖SVG进行的二次开发.建议初学者先学习svg里相关属性,便于在阅读jointJs的API或者de ...

  8. Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。

    精彩理解:  https://www.jianshu.com/p/21be831e851e ;  https://blog.csdn.net/heyutao007/article/details/19 ...

  9. [转]jsPlumb插件做一个模仿viso的可拖拉流程图

    原贴:https://www.cnblogs.com/sggx/p/3836432.html 前言 这是我第一次写博客,心情还是有点小小的激动!这次主要分享的是用jsPlumb,做一个可以给用户自定义 ...

随机推荐

  1. acm数论之旅--欧拉函数的证明

    随笔 - 20  文章 - 0  评论 - 73 ACM数论之旅7---欧拉函数的证明及代码实现(我会证明都是骗人的╮( ̄▽ ̄)╭) https://blog.csdn.net/chen_ze_hua ...

  2. 一周搞定模拟电路P3_电容_记录

    1 电容的介绍 什么是电容 它有两个电极板,和中间板所夹的介质封装而成,具有特定功能的电子器件. 电容的作用 旁路.去耦.滤波和储能的作用 2 旁路电容的作用 1)使输入电压均匀化,减少噪声对后级的影 ...

  3. tp5 自定义公共函数,前台模板调用

    最近用tp5做一个cms,在添加模型的时候,选择类型,这类型太多了,如果一个个的去判断显示,能累死人了,干脆写个公共方法, 首先写公共方法用到Common.php,目录project/applicat ...

  4. eclipse链接mySQL数据库常见错误

    1错误: 解决: 2,用户名输入错误 解决:查看自己的正确用户名https://zhidao.baidu.com/question/248308313.html 3. 解决: 链接示例:https:/ ...

  5. Jmeter_正则表达式提取器_提取数组 & For Each 控制器

    1.举例: https://demodaojia.ecjia.com/ 提取黄色标注的这些内容 2. 3. 匹配数字:-1 表示匹配全部,0表示随机一个 4. 5.我们获取了10组数据,通过正则提取器 ...

  6. Django 单元测试笔记

    引言 关于单元测试的基本知识这里不再讲述,简单一句话:单元测试是用一段代码去测试另一段代码.最常用的框架是unittest,这是python的单元测试框架,而django单元测试框架test.Test ...

  7. numpy.bincount正确理解

    今天看了个方法,numpy.bincount首先官网文档: numpy.bincount numpy.bincount(x, weights=None, minlength=0) Count numb ...

  8. 4_1 古老的密码(UVa1339)<排序>

    古罗马帝国与各部门有一个强有力的政府系统,包括一个秘密服务部门.重要的文件以加密的形式发送防止窃听.在那个时代最流行的密码被称为替代密码和置换密码.例如,应用替代密码,改变所有字母“A”到“Y”字母表 ...

  9. 洛谷P1006传纸条

    题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个 m 行 n 列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了. ...

  10. 安装 Python 虚拟环境 (Linux)

    我的 Ubuntu 18.04 预安装了 python 3.6,但是没有安装 pip,所以先进行安装: apt-get install python-pip 1. 安装虚拟环境所需包: pip ins ...