目录

  • JointJS:JavaScript 流程图绘制框架

    • JointJS 简介
    • JointJS Hello world
    • 前后端分离架构
    • 其他
      • 自动布局 Automatic layout
      • 使用 HTML 定制元素

JointJS:JavaScript 流程图绘制框架

最近调研了js画流程图的框架,最后选择了Joint。配合上 dagre 可以画出像模像样的流程图。

JointJS 简介

JointJS 是一个开源前端框架,支持绘制各种各样的流程图、工作流图等。Rappid 是 Joint 的商业版,提供了一些更强的插件。JointJS 的特点有下面几条,摘自官网:

  • 能够实时地渲染上百(或者上千)个元素和连接
  • 支持多种形状(矩形、圆、文本、图像、路径等)
  • 高度事件驱动,用户可自定义任何发生在 paper 下的事件响应
  • 元素间连接简单
  • 可定制的连接和关系图
  • 连接平滑(基于贝塞尔插值 bezier interpolation)& 智能路径选择
  • 基于 SVG 的可定制、可编程的图形渲染
  • NodeJS 支持
  • 通过 JSON 进行序列化和反序列化

总之 JoingJS 是一款很强的流程图制作框架,开源版本已经足够日常使用了。

一些常用地址:

API: https://resources.jointjs.com/docs/jointjs/v1.1/joint.html

Tutorials: https://resources.jointjs.com/tutorial

JointJS Hello world

<!DOCTYPE html>
<html>
<head><link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.css" />
</head>
<body><!-- content --><div id="myholder"></div><!-- dependencies 通过CDN加载依赖--><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.js"></script><!-- code --><script type="text/javascript">var graph = new joint.dia.Graph;var paper = new joint.dia.Paper({el: document.getElementById('myholder'),model: graph,width: 600,height: 100,gridSize: 1});var rect = new joint.shapes.standard.Rectangle();rect.position(100, 30);rect.resize(100, 40);rect.attr({body: {fill: 'blue'},label: {text: 'Hello',fill: 'white'}});rect.addTo(graph);var rect2 = rect.clone();rect2.translate(300, 0);rect2.attr('label/text', 'World!');rect2.addTo(graph);var link = new joint.shapes.standard.Link();link.source(rect);link.target(rect2);link.addTo(graph);</script>
</body>
</html>

hello world 代码没什么好说的。要注意这里的图形并没有自动排版,而是通过移动第二个 rect 实现的手动排版。

前后端分离架构

既然支持 NodeJs,那就可以把繁重的图形绘制任务交给服务器,再通过 JSON 序列化在 HTTP 上传输对象,这样减轻客户端的压力。

NodeJS 后端

var express = require('express');
var joint = require('jointjs');var app = express();function get_graph(){var graph = new joint.dia.Graph();var rect = new joint.shapes.standard.Rectangle();rect.position(100, 30);rect.resize(100, 40);rect.attr({body: {fill: 'blue'},label: {text: 'Hello',fill: 'white'}});rect.addTo(graph);var rect2 = rect.clone();rect2.translate(300, 0);rect2.attr('label/text', 'World!');rect2.addTo(graph);var link = new joint.shapes.standard.Link();link.source(rect);link.target(rect2);link.addTo(graph);return graph.toJSON();
}app.all('*', function(req, res, next) {res.header("Access-Control-Allow-Origin", "*");res.header("Access-Control-Allow-Headers", "X-Requested-With");res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");next();
});app.get('/graph', function(req, res){console.log('[+] send graph json to client')res.send(get_graph());
});app.listen(8071);

HTML 前端

<!DOCTYPE html>
<html>
<head><link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.css" />
</head>
<body><!-- content --><div id="myholder"></div><!-- dependencies 通过CDN加载依赖--><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.js"></script><!-- code --><script type="text/javascript">var graph = new joint.dia.Graph;var paper = new joint.dia.Paper({el: document.getElementById('myholder'),model: graph,width: 600,height: 100,gridSize: 1});$.get('http://192.168.237.128:8071/graph', function(data, statue){graph.fromJSON(data);});</script>
</body>
</html>

其他

自动布局 Automatic layout

JointJS 内置了插件进行自动排版,原理是调用 Dagre 库。官方 api 中有样例。

使用方法:

var graphBBox = joint.layout.DirectedGraph.layout(graph, {
nodeSep: 50,
edgeSep: 80,
rankDir: "TB"
});

配置参数 注释
nodeSep 相同rank的邻接节点的距离
edgeSep 相同rank的邻接边的距离
rankSep 不同 rank 元素之间的距离
rankDir 布局方向 ( "TB" (top-to-bottom) / "BT" (bottom-to-top) / "LR" (left-to-right) / "RL" (right-to-left))
marginX number of pixels to use as a margin around the left and right of the graph.
marginY number of pixels to use as a margin around the top and bottom of the graph.
ranker 排序算法。 Possible values: 'network-simplex' (default), 'tight-tree' or 'longest-path'.
resizeClusters set to false if you don't want parent elements to stretch in order to fit all their embedded children. Default is true.
clusterPadding A gap between the parent element and the boundary of its embedded children. It could be a number or an object e.g. { left: 10, right: 10, top: 30, bottom: 10 }. It defaults to 10.
setPosition(element, position) a function that will be used to set the position of elements at the end of the layout. This is useful if you don't want to use the default element.set('position', position) but want to set the position in an animated fashion via transitions.
setVertices(link, vertices) If set to true the layout will adjust the links by setting their vertices. It defaults to false. If the option is defined as a function it will be used to set the vertices of links at the end of the layout. This is useful if you don't want to use the default link.set('vertices', vertices) but want to set the vertices in an animated fashion via transitions.
setLabels(link, labelPosition, points) If set to true the layout will adjust the labels by setting their position. It defaults to false. If the option is defined as a function it will be used to set the labels of links at the end of the layout. Note: Only the first label (link.label(0);) is positioned by the layout.
dagre 默认情况下,dagre 应该在全局命名空间当中,不过你也可以当作参数传进去
graphlib 默认情况下,graphlib 应该在全局命名空间当中,不过你也可以当作参数传进去

我们来试一下。NodeJS 后端

var express = require('express');
var joint = require('jointjs');
var dagre = require('dagre')
var graphlib = require('graphlib');var app = express();function get_graph(){var graph = new joint.dia.Graph();var rect = new joint.shapes.standard.Rectangle();rect.position(100, 30);rect.resize(100, 40);rect.attr({body: {fill: 'blue'},label: {text: 'Hello',fill: 'white'}});rect.addTo(graph);var rect2 = rect.clone();rect2.translate(300, 0);rect2.attr('label/text', 'World!');rect2.addTo(graph);for(var i=0; i<10; i++){var cir = new joint.shapes.standard.Circle();cir.resize(100, 100);cir.position(10, 10);cir.attr('root/title', 'joint.shapes.standard.Circle');cir.attr('label/text', 'Circle' + i);cir.attr('body/fill', 'lightblue');cir.addTo(graph);var ln = new joint.shapes.standard.Link();ln.source(cir);ln.target(rect2);ln.addTo(graph);}var link = new joint.shapes.standard.Link();link.source(rect);link.target(rect2);link.addTo(graph);//auto  layoutjoint.layout.DirectedGraph.layout(graph, {nodeSep: 50,edgeSep: 50,rankDir: "TB",dagre: dagre,graphlib: graphlib});return graph.toJSON();
}app.all('*', function(req, res, next) {res.header("Access-Control-Allow-Origin", "*");res.header("Access-Control-Allow-Headers", "X-Requested-With");res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");next();
});app.get('/graph', function(req, res){console.log('[+] send graph json to client')res.send(get_graph());
});app.listen(8071);

HTML 前端

<!DOCTYPE html>
<html>
<head><link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.css" />
</head>
<body><!-- content --><div id="myholder"></div><!-- dependencies 通过CDN加载依赖--><script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone.js"></script><script src="https://cdnjs.cloudflare.com/ajax/libs/jointjs/2.1.0/joint.js"></script><!-- code --><script type="text/javascript">var graph = new joint.dia.Graph;var paper = new joint.dia.Paper({el: document.getElementById('myholder'),model: graph,width: 2000,height: 2000,gridSize: 1});$.get('http://192.168.237.128:8071/graph', function(data, statue){graph.fromJSON(data);});</script>
</body>
</html>

结果:

使用 HTML 定制元素

流程图中的每个点,也就是是元素,都可以自定义,直接编写 html 代码能添加按钮、输入框、代码块等。

我的一个代码块 demo,搭配 highlight.js 可以达到类似 IDA 控制流图的效果。这个 feature 可玩度很高。

joint.shapes.BBL = {};
joint.shapes.BBL.Element = joint.shapes.basic.Rect.extend({defaults: joint.util.deepSupplement({type: 'BBL.Element',attrs: {rect: { stroke: 'none', 'fill-opacity': 0 }}}, joint.shapes.basic.Rect.prototype.defaults)
});// Create a custom view for that element that displays an HTML div above it.
// -------------------------------------------------------------------------
joint.shapes.BBL.ElementView = joint.dia.ElementView.extend({template: ['<div class="html-element" data-collapse>','<label></label><br/>','<div class="hljs"><pre><code></code></pre></span></div>','</div>'].join(''),initialize: function() {_.bindAll(this, 'updateBox');joint.dia.ElementView.prototype.initialize.apply(this, arguments);this.$box = $(_.template(this.template)());// Prevent paper from handling pointerdown.this.$box.find('h3').on('mousedown click', function(evt) {evt.stopPropagation();});// Update the box position whenever the underlying model changes.this.model.on('change', this.updateBox, this);// Remove the box when the model gets removed from the graph.this.model.on('remove', this.removeBox, this);this.updateBox();},render: function() {joint.dia.ElementView.prototype.render.apply(this, arguments);this.paper.$el.prepend(this.$box);this.updateBox();return this;},updateBox: function() {// Set the position and dimension of the box so that it covers the JointJS element.var bbox = this.model.getBBox();// Example of updating the HTML with a data stored in the cell model.this.$box.find('label').text(this.model.get('label'));this.$box.find('code').html(this.model.get('code'));var color = this.model.get('color');this.$box.css({width: bbox.width,height: bbox.height,left: bbox.x,top: bbox.y,background: color,"border-color": color});},removeBox: function(evt) {this.$box.remove();}
});

转载于:https://www.cnblogs.com/helica/p/11354577.html

JointJS:JavaScript 流程图绘制框架相关推荐

  1. 解析HTML流程图,JointJS JavaScript流程图绘制框架解析

    JointJS:JavaScript 流程图绘制框架 最近调研了js画流程图的框架,最后选择了Joint.配合上 dagre 可以画出像模像样的流程图. JointJS 简介 JointJS 是一个开 ...

  2. Web流程图绘制使用raphael

    摘要:本文要实现一个流程图的绘制,最终的目标是实现流程图的自动绘制,并可进行操作,直接点击流程图上对应的方框就可以让后台跑相应的程序. 一.插件介绍 1.图形绘制raphael 其中图形绘制使用了ra ...

  3. 推荐12个最好的 JavaScript 图形绘制库

    众多周知,图形和图表要比文本更具表现力和说服力.图表是数据图形化的表示,通过形象的图表来展示数据,比如条形图,折线图,饼图等等.可视化图表可以帮助开发者更容易理解复杂的数据,提高生产的效率和 Web  ...

  4. jquery实现流程图绘制工具——展现红警三建造出兵操作 ——一 简介

    作为一名红警三玩家,为了提高自己的技术,我会时不时的看一些别人的录像来学习,所以想要对录像的信息进行一定的记录. 单纯用文字是很麻烦的,且不够直观,容易啰嗦. 故而我有这样一个想法: 能否用图表比较详 ...

  5. er图转为数据流程图_draw.io for Mac(流程图绘制工具)

    http://draw.io Mac版是Mac平台上的一款流程图绘制工具.http://draw.io Mac版是一款非常好用的绘制流程图的工具,提供了流程图,UML图等丰富的接口.它还支持第三方云存 ...

  6. 绘制业务流程图:流程图绘制工具

    文章描述:什么是流程图?流程图和其他图表(如线框图,概念图,架构图,用例图)有什么不同? 图1:用即时贴与白板做的简单流程图 转载请注明来处,关注我请点击:http://weibo.com/heidi ...

  7. 【PC工具】更新在线流程图绘制工具bullmind,免费云存储流程图绘制,可直接粘贴图片...

    上次推荐了bullmind,今天谈谈使用感受,再推荐一款类似的软件. 先发个bullmind快捷键: 每次进入都会提示上边的快捷键,为什么我要发呢?因为"创建标签"(快捷键t)和双 ...

  8. markdown 流程图js_科学网—让Markdown支持ASCII流程图和JavaScript流程图 - 李继存的博文...

    2014-12-25 12:08:34 计算机领域中一直存在两种不同的理念并彼此竞争, 可视化与可控化, 或称为所见即所得与所愿即所得. 前者是Windows的典型做法, 而后者是Linux的典型理念 ...

  9. 强大的流程图绘制控件WpfDiagram

    为什么80%的码农都做不了架构师?>>>    WpfDiagram是一款功能强大的流程图绘制控件,可以绘制工作流程图.对象层次和关系图.网络拓扑图.实体关系图.IVR.工业自动化. ...

最新文章

  1. Windows Server 2016 部署Hyper-V
  2. mysql localhost和127.0.0.1的区别
  3. 【日常分享1】三步,有效去除网页广告,完美过滤视频广告
  4. php 根据数组归类,PHP如何高效地对根据键值对数组元素进行归类?
  5. 【c语言 gcc9.1.0环境下编译报错】error: ‘true’ undeclared (first use in this function)
  6. gif android 点击 加载,android 加载显示gif图片的解决方案
  7. 大坑!有网,电脑qq登不上去!!
  8. Android控件捕获点击事件的范围
  9. 聊聊安卓折叠屏给交互设计和开发带来的变化
  10. count函数里加函数_PHP count()函数与示例
  11. 白盒测试中的六种覆盖方法及案例分析
  12. ActiveMQ学习(三)——MQ的通讯模式
  13. Linux配置nginx打开报404,Linux下Nginx配置404页面的方法
  14. python随笔系列--多进程多线程并发度初探
  15. git jenkins 子目录,在Jenkins中,如何将项目签出到特定目录(使用GIT)
  16. 监控视频统一汇聚集中录像存储方案
  17. python改变背景颜色_Python实现转换图片背景颜色代码
  18. c语言中指数形式怎么表示_C语言编程基础知识汇总学习,适合初学者!
  19. 中国探月计算机考试时间,中国探月工程三级跳:嫦娥一号到嫦娥三号
  20. 内网渗透系列:横向渗透方法小结

热门文章

  1. 一文读懂数据中台架构体系(收藏)
  2. 计算机编程与ug编程,UG编程完整版.doc
  3. java将图片转化为pdf并输出
  4. 小程序毕设作品之微信在线教育视频点播学习小程序毕业设计(7)中期检查报告
  5. 2023年JDK收费临时解决方案
  6. 【webrtc】 socket 运行机制以及 stun 收发过程
  7. ffmpeg-给视频添加字幕(二十四)
  8. ORACLE 的SCHEDULER创建JOB
  9. 微信小程序开发教程之Array数组对象
  10. LOJ 2547 「JSOI2018」防御网络——思路+环DP