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的淡入淡出的特效基础练习
Dec 13 Javascript
jquery绑定原理 简单解析与实现代码分享
Sep 06 Javascript
jquery如何扑捉回车键触发的事件
Apr 24 Javascript
采用自执行的匿名函数解决for循环使用闭包的问题
Sep 11 Javascript
jquery插件jSignature实现手动签名
May 04 Javascript
基于javascript实现窗口抖动效果
Jan 03 Javascript
小程序显示弹窗时禁止下层的内容滚动实现方法
Mar 20 Javascript
javascript设计模式 ? 简单工厂模式原理与应用实例分析
Apr 09 Javascript
javaScript代码飘红报错看不懂?读完这篇文章再试试
Aug 19 Javascript
javascript实现一款好看的秒表计时器
Sep 05 Javascript
js实现随机圆与矩形功能
Oct 29 Javascript
微信小程序实现轮播图指示器
Jun 25 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
全国FM电台频率大全 - 31 新疆维吾尔族自治区
2020/03/11 无线电
使用PHP和JavaScript判断请求是否来自微信内浏览器
2015/08/18 PHP
PHP与jquery实时显示网站在线人数实例详解
2016/12/02 PHP
jQuery TextBox自动完成条
2009/07/22 Javascript
jQuery ajax在GBK编码下表单提交终极解决方案(非二次编码方法)
2010/10/20 Javascript
JQuery动态创建DOM、表单元素的实现代码
2011/08/09 Javascript
JavaScript定时显示广告代码分享
2015/03/02 Javascript
Bootstrap每天必学之简单入门
2015/11/19 Javascript
Javascript中数组去重与拍平的方法示例
2017/02/03 Javascript
SpringMVC+bootstrap table实例详解
2017/06/02 Javascript
AngularJS监听ng-repeat渲染完成的两种方法
2018/01/16 Javascript
基于JavaScript实现一个简单的Vue
2018/09/26 Javascript
详解服务端预渲染之Nuxt(介绍篇)
2019/04/07 Javascript
Vue实现商品详情页的评价列表功能
2019/09/04 Javascript
用原生JS实现爱奇艺首页导航栏代码实例
2019/09/19 Javascript
解决Layui当中的导航条动态添加后渲染失败的问题
2019/09/25 Javascript
layui实现显示数据表格、搜索和修改功能示例
2020/06/03 Javascript
js+canvas实现图片格式webp/png/jpeg在线转换
2020/08/22 Javascript
Python 专题一 函数的基础知识
2017/03/16 Python
Python拼接微信好友头像大图的实现方法
2018/08/01 Python
Django实现学员管理系统
2019/02/26 Python
python中报错&quot;json.decoder.JSONDecodeError: Expecting value:&quot;的解决
2019/04/29 Python
python实现网站用户名密码自动登录功能
2019/08/09 Python
django与vue的完美结合_实现前后端的分离开发之后在整合的方法
2019/08/12 Python
PyCharm无法引用自身项目解决方式
2020/02/12 Python
css sprite简单实例
2016/05/23 HTML / CSS
HTML5 Canvas的事件处理介绍
2015/04/24 HTML / CSS
Fossil美国官网:化石手表、手袋、首饰及配饰
2019/02/17 全球购物
Oracle里面常用的数据字典有哪些
2014/02/14 面试题
母亲七十大寿答谢词
2014/01/18 职场文书
汽车装潢店创业计划书范文
2014/02/05 职场文书
排查整治工作方案
2014/06/09 职场文书
会议开幕致辞怎么写
2016/03/03 职场文书
婚前协议书怎么写,才具有法律效力呢 ?
2019/06/28 职场文书
Python开发简易五子棋小游戏
2022/05/02 Python
python pandas 解析(读取、写入)CSV 文件的操作方法
2022/12/24 Python