麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 編程 > JavaScript > 正文

JointJS JavaScript流程圖繪制框架解析

2019-11-19 11:02:02
字體:
來源:轉載
供稿:網友

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"  rel="external nofollow" rel="external nofollow" rel="external nofollow" /></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"  rel="external nofollow" rel="external nofollow" rel="external nofollow" /></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 layout  joint.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"  rel="external nofollow" rel="external nofollow" rel="external nofollow" /></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();  }});

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 日韩美香港a一级毛片 | 男女无套免费视频 | 成人免费网视频 | 九九热在线视频观看 | 欧美黄 片免费观看 | 黄色片一区二区 | 欧美一区二区三区免费不卡 | 成人三级黄色片 | 黑人一区 | 91av在线免费观看 | 亚洲精品成人在线视频 | 日韩黄色片在线观看 | 激情视频免费观看 | 91网站永久免费看 | 国产在线免 | 国产精品久久久久久久久久东京 | 中文字幕伦乱 | 日韩中文字幕一区二区三区 | 国产毛片自拍 | 日本一级黄色大片 | 国产精品剧情一区二区三区 | 日本免费a∨ | 日日操夜夜透 | 日日操夜夜透 | 久久网站热最新地址 | 精品亚洲视频在线 | 国产精品视频一区二区三区四区五区 | 久久草在线视频 | 成人三级免费电影 | 性爱免费在线视频 | 一级做受大片免费视频 | 久久精品国产亚洲7777小说 | 久久网国产精品 | 免费视频a | 国产精品自拍99 | 中文字幕在线免费播放 | 久久国产亚洲视频 | 欧美精品欧美极品欧美激情 | 成人午夜视频在线观看 | 精品在线视频观看 | 一区二区精品视频在线观看 |