JointJS流程图的绘制方法


Posted in Javascript onDecember 03, 2018

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

jsPlumb地址:https://jsplumbtoolkit.com

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

JointJS流程图的绘制方法

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

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">×</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();
 }
 
 });

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery判断checkbox(复选框)是否被选中的代码
Oct 20 Javascript
兼容IE、firefox以及chrome的js获取时间(getFullYear)
Jul 04 Javascript
javascript实现字符串反转的方法
Feb 05 Javascript
jquery实现可点击伸缩与展开的菜单效果代码
Aug 31 Javascript
浅谈node.js中async异步编程
Oct 22 Javascript
图解Sublime Text3使用技巧
Dec 21 Javascript
js实现简单的选项卡效果
Feb 23 Javascript
JavaScript实现的原生态Tab标签页功能【兼容IE6】
Sep 18 Javascript
浅谈Angular 中何时取消订阅
Nov 22 Javascript
实例介绍JavaScript中多种组合继承
Jan 20 Javascript
一个小时快速搭建微信小程序的方法步骤
Apr 15 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
Jul 17 Javascript
微信小程序之事件交互操作实例分析
Dec 03 #Javascript
vue-better-scroll 的使用实例代码详解
Dec 03 #Javascript
Vue项目中使用better-scroll实现一个轮播图自动播放功能
Dec 03 #Javascript
Vue.js 图标选择组件实践详解
Dec 03 #Javascript
vue-music 使用better-scroll遇到轮播图不能自动轮播问题
Dec 03 #Javascript
vue-cli3.0+element-ui上传组件el-upload的使用
Dec 03 #Javascript
利用jquery和BootStrap实现动态滚动条效果
Dec 03 #jQuery
You might like
PHP动态变静态原理
2006/11/25 PHP
PHP fopen 读取带中文URL地址的一点见解
2012/09/25 PHP
javascript 面向对象,实现namespace,class,继承,重载
2009/10/29 Javascript
JavaScript 语法集锦 脚本之家基础推荐
2009/11/15 Javascript
Ubuntu 11.10 安装Node.js的方法
2011/11/30 Javascript
javascript控制swfObject应用介绍
2012/11/29 Javascript
实现点击列表弹出列表索引的两种方式
2013/03/08 Javascript
jQuery动态地获取系统时间实现代码
2013/05/24 Javascript
jquery easyui 结合jsp简单展现table数据示例
2014/04/18 Javascript
用unescape反编码得出汉字示例
2014/04/24 Javascript
AngularJS基础教程之简单介绍
2015/09/27 Javascript
Angular 应用技巧总结
2016/09/14 Javascript
JavaScript无阻塞加载和defer、async详解
2017/02/26 Javascript
微信{"errcode":48001,"errmsg":"api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]"}
2018/10/12 Javascript
[01:10]DOTA2次级职业联赛 - U5战队宣传片
2014/12/01 DOTA
[02:30]联想杯DOTA2完美世界全国高校联赛—北京站现场
2015/11/16 DOTA
[40:16]TFT vs Mski Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
python根据时间生成mongodb的ObjectId的方法
2015/03/13 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
使用python模拟命令行终端的示例
2019/08/13 Python
使用python写的opencv实时监测和解析二维码和条形码
2019/08/14 Python
详解anaconda离线安装pytorchGPU版
2020/09/08 Python
python实现canny边缘检测
2020/09/14 Python
使用py-spy解决scrapy卡死的问题方法
2020/09/29 Python
借助HTML5 Canvas API制作一个简单的猜字游戏
2016/03/25 HTML / CSS
琳达·法罗眼镜英国官网:Linda Farrow英国
2021/01/19 全球购物
优秀的教师个人的中文求职信
2013/09/21 职场文书
财务部岗位职责
2013/11/19 职场文书
“向国旗敬礼”活动策划方案(4篇)
2014/09/27 职场文书
2016年国陪研修感言
2015/11/18 职场文书
八年级数学教学反思
2016/02/17 职场文书
《围炉夜话》110句人生箴言,精辟有内涵,引人深思
2019/10/23 职场文书
2019年世界儿童日宣传标语
2019/11/22 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
如何设置多台电脑共享打印机?多台电脑共享打印机的方法
2022/04/08 数码科技