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版Tab标签切换
Mar 16 Javascript
jQuery动态添加 input type=file的实现代码
Jun 14 Javascript
javascript计算星座属相(十二生肖属相)示例代码
Jan 09 Javascript
JavaScript判断文件上传类型的方法
Sep 02 Javascript
jQuery EasyUI基础教程之EasyUI常用组件(推荐)
Jul 15 Javascript
jQuery使用ajax方法解析返回的json数据功能示例
Jan 10 Javascript
深入理解Angular中的依赖注入
Jun 26 Javascript
帝国cms首页列表页实现点赞功能
Oct 30 Javascript
JS脚本加载后执行相应回调函数的操作方法
Feb 28 Javascript
详解js的视频和音频采集
Aug 09 Javascript
webpack中的模式(mode)使用详解
Feb 20 Javascript
vuex刷新后数据丢失的解决方法
Oct 18 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
改造一台复古桌面收音机
2021/03/02 无线电
咖啡界又出新概念,无需咖啡豆的分子咖啡
2021/03/03 咖啡文化
PHP将DateTime对象转化为友好时间显示的实现代码
2011/09/20 PHP
怎样使用php与jquery设置和读取cookies
2013/08/08 PHP
php获取参数的几种方法总结
2014/02/18 PHP
PHP使用strtotime计算两个给定日期之间天数的方法
2015/03/18 PHP
php微信公众号js-sdk开发应用
2016/11/28 PHP
详解php用curl调用接口方法,get和post两种方式
2017/01/13 PHP
PHP unlink与rmdir删除目录及目录下所有文件实例代码
2018/02/07 PHP
PHP get_html_translation_table()函数用法讲解
2019/02/16 PHP
Javascript面象对象成员、共享成员变量实验
2010/11/19 Javascript
JS将制定内容复制到剪切板示例代码
2014/02/11 Javascript
Javascript核心读书有感之表达式和运算符
2015/02/11 Javascript
Javascript中实现String.startsWith和endsWith方法
2015/06/10 Javascript
javascript中JSON对象与JSON字符串相互转换实例
2015/07/11 Javascript
js验证框架实现代码分享
2016/05/18 Javascript
详解Nuxt.js中使用Element-UI填坑
2019/09/06 Javascript
Vue实现仿iPhone悬浮球的示例代码
2020/03/13 Javascript
JS数组reduce()方法原理及使用技巧解析
2020/07/14 Javascript
Python环境搭建之OpenCV的步骤方法
2017/10/20 Python
基于python实现高速视频传输程序
2019/05/05 Python
python:动态路由的Flask程序代码
2019/11/22 Python
Keras实现DenseNet结构操作
2020/07/06 Python
Python获取浏览器窗口句柄过程解析
2020/07/25 Python
用python制作个视频下载器
2021/02/01 Python
如何用border-image实现文字气泡边框的示例代码
2020/01/21 HTML / CSS
英国排名第一的停车场运营商:NCP
2019/08/26 全球购物
中文专业毕业生自荐信
2013/10/28 职场文书
飞机制造技术专业求职信
2014/07/27 职场文书
博士生专家推荐信
2014/09/26 职场文书
收款授权委托书
2014/10/02 职场文书
白酒代理协议书范本
2014/10/26 职场文书
新婚姻法离婚协议书范文
2014/11/30 职场文书
班主任班级管理心得体会
2016/01/07 职场文书
解决SpringCloud Feign传对象参数调用失败的问题
2021/06/23 Java/Android
Docker安装MySql8并远程访问的实现
2022/07/07 Servers