最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JointJS JavaScript流程圖繪制框架解析

 更新時間:2019年08月15日 14:09:39   作者:Helica  
這篇文章主要介紹了JointJS JavaScript流程圖繪制框架解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

JointJS:JavaScript 流程圖繪制框架

最近調(diào)研了js畫流程圖的框架,最后選擇了Joint。配合上 dagre 可以畫出像模像樣的流程圖。

JointJS 簡介

JointJS 是一個開源前端框架,支持繪制各種各樣的流程圖、工作流圖等。Rappid 是 Joint 的商業(yè)版,提供了一些更強的插件。JointJS 的特點有下面幾條,摘自官網(wǎng):

  • 能夠?qū)崟r地渲染上百(或者上千)個元素和連接
  • 支持多種形狀(矩形、圓、文本、圖像、路徑等)
  • 高度事件驅(qū)動,用戶可自定義任何發(fā)生在 paper 下的事件響應(yīng)
  • 元素間連接簡單
  • 可定制的連接和關(guān)系圖
  • 連接平滑(基于貝塞爾插值 bezier interpolation)& 智能路徑選擇
  • 基于 SVG 的可定制、可編程的圖形渲染
  • NodeJS 支持
  • 通過 JSON 進行序列化和反序列化

總之 JoingJS 是一款很強的流程圖制作框架,開源版本已經(jīng)足夠日常使用了。

一些常用地址:

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 實現(xiàn)的手動排版。

前后端分離架構(gòu)

既然支持 NodeJs,那就可以把繁重的圖形繪制任務(wù)交給服務(wù)器,再通過 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 內(nèi)置了插件進行自動排版,原理是調(diào)用 Dagre 庫。官方 api 中有樣例。

使用方法:

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

配置參數(shù) 注釋
nodeSep 相同rank的鄰接節(jié)點的距離
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 應(yīng)該在全局命名空間當中,不過你也可以當作參數(shù)傳進去
graphlib 默認情況下,graphlib 應(yīng)該在全局命名空間當中,不過你也可以當作參數(shù)傳進去

我們來試一下。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>

結(jié)果:

使用 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();
  }
});

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 用js判斷是否為360瀏覽器的實現(xiàn)代碼

    用js判斷是否為360瀏覽器的實現(xiàn)代碼

    這篇文章主要介紹了用js判斷是否為360瀏覽器的實現(xiàn)代碼,有時候我們需要判斷是否為360瀏覽器,包括百度聯(lián)盟后臺就有這樣的提示需要的朋友可以參考下
    2015-01-01
  • JavaScript中document獲取元素方法示例詳解

    JavaScript中document獲取元素方法示例詳解

    這篇文章主要介紹了JavaScript中獲取頁面元素的幾種常用方法,分別是getElementById()、getElementsByClassName()、getElementsByTagName()、querySelector()和querySelectorAll(),每種方法都有其特點和適用場景,需要的朋友可以參考下
    2025-03-03
  • JS制作圖形驗證碼實現(xiàn)代碼

    JS制作圖形驗證碼實現(xiàn)代碼

    這篇文章主要為大家詳細介紹了JS制作圖形驗證碼實現(xiàn)代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • JavaScript 中使用 Generator的方法

    JavaScript 中使用 Generator的方法

    Generator 是一種非常強力的語法,但它的使用并不廣泛。這篇文章主要介紹了如何在 JavaScript 中使用 Generator,需要的朋友可以參考下
    2017-12-12
  • JS實現(xiàn)FLASH幻燈片圖片切換效果的方法

    JS實現(xiàn)FLASH幻燈片圖片切換效果的方法

    這篇文章主要介紹了JS實現(xiàn)FLASH幻燈片圖片切換效果的方法,實例分析了javascript操作圖片實現(xiàn)Flash幻燈效果的技巧,需要的朋友可以參考下
    2015-03-03
  • 深入淺析JS中的嚴格模式

    深入淺析JS中的嚴格模式

    嚴格模式就是使JS編碼更加規(guī)范化的模式,消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為。下面通過代碼相結(jié)合的形式給大家介紹js中的嚴格模式,感興趣的朋友一起看看吧
    2018-06-06
  • JavaScript中獲取鼠標位置相關(guān)屬性總結(jié)

    JavaScript中獲取鼠標位置相關(guān)屬性總結(jié)

    這篇文章主要介紹了JavaScript中獲取鼠標位置相關(guān)屬性總結(jié),本文重點在搞清楚這些屬性的區(qū)別,需要的朋友可以參考下
    2014-10-10
  • Js獲取當前日期時間及格式化代碼

    Js獲取當前日期時間及格式化代碼

    這篇文章主要為大家詳細介紹了Js獲取當前日期時間及格式化代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • 基于JavaScript實現(xiàn)的插入排序算法分析

    基于JavaScript實現(xiàn)的插入排序算法分析

    這篇文章主要介紹了基于JavaScript實現(xiàn)的插入排序算法,結(jié)合實例形式詳細分析了插入排序的原理、操作步驟及javascript相關(guān)實現(xiàn)技巧與注意事項,需要的朋友可以參考下
    2017-04-04
  • JavaScript性能優(yōu)化總結(jié)之加載與執(zhí)行

    JavaScript性能優(yōu)化總結(jié)之加載與執(zhí)行

    本文詳細介紹了如何正確的加載和執(zhí)行JavaScript代碼,從而提高其在瀏覽器中的性能。對JavaScript學(xué)習(xí)者很有幫助,有需要的可以參考學(xué)習(xí)。
    2016-08-08

最新評論

抚顺市| 木兰县| 昌邑市| 漳平市| 巨鹿县| 高唐县| 长宁县| 黔西县| 威宁| 兴隆县| 张家口市| 黄龙县| 台北县| 滨海县| 收藏| 盖州市| 灵寿县| 南投市| 米泉市| 宁夏| 原阳县| 吉木萨尔县| 阳谷县| 德令哈市| 永丰县| 会泽县| 鹤峰县| 黎城县| 宁都县| 霍山县| 柘城县| 永城市| 常德市| 汉川市| 遵义县| 泸水县| 堆龙德庆县| 炉霍县| 湛江市| 玉树县| 九台市|