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 相关文章推荐
[原创]网络复制内容时常用的正则+editplus
Nov 30 Javascript
jQuery 使用手册(四)
Sep 23 Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
Jul 21 Javascript
jquery制作LED 时钟特效
Feb 01 Javascript
JavaScript控制listbox列表框的项目上下移动的方法
Mar 18 Javascript
简单实现的JQuery文本框水印插件
Jun 14 Javascript
浅谈JavaScript中的分支结构
Jul 01 Javascript
Vue.js 2.0中select级联下拉框实例
Mar 06 Javascript
jQuery序列化后的表单值转换成Json
Jun 16 jQuery
浅析vue-router jquery和params传参(接收参数)$router $route的区别
Aug 03 jQuery
vue3.0实现插件封装
Dec 14 Vue.js
js面向对象封装级联下拉菜单列表的实现步骤
Feb 08 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 类商品秒杀计时实现代码
2010/05/05 PHP
php下尝试使用GraphicsMagick的缩略图功能
2011/01/01 PHP
使用ThinkPHP+Uploadify实现图片上传功能
2014/06/26 PHP
PHP生成加减算法方式的验证码实例
2018/03/12 PHP
PHP PDOStatement::bindParam讲解
2019/01/30 PHP
javascript 显示当前系统时间代码
2009/12/28 Javascript
添加JavaScript重载函数的辅助方法2
2010/07/04 Javascript
关于jQuery object and DOM element
2013/04/15 Javascript
JS验证邮箱格式是否正确的代码
2013/12/05 Javascript
JavaScript中的return语句简单介绍
2015/12/07 Javascript
Js 获取、判断浏览器版本信息的简单方法
2016/08/08 Javascript
浅谈jQuery中的checkbox问题
2016/08/10 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
2016/12/02 Javascript
详解如何使用vue-cli脚手架搭建Vue.js项目
2017/05/19 Javascript
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
vue-router项目实战总结篇
2018/02/11 Javascript
[59:00]OG vs TNC 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
对python mayavi三维绘图的实现详解
2019/01/08 Python
scrapy-redis的安装部署步骤讲解
2019/02/27 Python
Python合并2个字典成1个新字典的方法(9种)
2019/12/19 Python
python kafka 多线程消费者&amp;手动提交实例
2019/12/21 Python
Python通过4种方式实现进程数据通信
2020/03/12 Python
翻转数列python实现,求前n项和,并能输出整个数列的案例
2020/05/03 Python
详解matplotlib绘图样式(style)初探
2021/02/03 Python
HTML5 Canvas实现360度全景图的示例代码
2018/01/29 HTML / CSS
在家更换处方镜片:Lensabl
2019/05/01 全球购物
世嘉游戏英国官方商店:SEGA Shop UK
2019/09/20 全球购物
阿迪达斯印尼官方网站:adidas印尼
2020/02/10 全球购物
华为消费者德国官方网站:HUAWEI德国
2020/11/03 全球购物
JVM是一个编译程序还是解释程序
2012/09/11 面试题
通信工程专业求职信
2014/06/04 职场文书
学校领导班子群众路线整改措施
2014/09/16 职场文书
2015年试用期自我评价范文
2015/03/10 职场文书
公司开会通知
2015/04/20 职场文书
2015年工程部工作总结
2015/04/30 职场文书
新郎接新娘保证书
2015/05/08 职场文书