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

JointJS JavaScript流程圖繪制框架解析

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

JointJS:JavaScript 流程圖繪制框架

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

JointJS 簡(jiǎn)介

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

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

總之 JoingJS 是一款很強(qiáng)的流程圖制作框架,開源版本已經(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 通過(guò)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 代碼沒什么好說(shuō)的。要注意這里的圖形并沒有自動(dòng)排版,而是通過(guò)移動(dòng)第二個(gè) rect 實(shí)現(xiàn)的手動(dòng)排版。

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

既然支持 NodeJs,那就可以把繁重的圖形繪制任務(wù)交給服務(wù)器,再通過(guò) JSON 序列化在 HTTP 上傳輸對(duì)象,這樣減輕客戶端的壓力。

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 通過(guò)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>

其他

自動(dòng)布局 Automatic layout

JointJS 內(nèi)置了插件進(jìn)行自動(dòng)排版,原理是調(diào)用 Dagre 庫(kù)。官方 api 中有樣例。

使用方法:

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

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

我們來(lái)試一下。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 通過(guò)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 定制元素

流程圖中的每個(gè)點(diǎn),也就是是元素,都可以自定義,直接編寫 html 代碼能添加按鈕、輸入框、代碼塊等。

我的一個(gè)代碼塊 demo,搭配 highlight.js 可以達(dá)到類似 IDA 控制流圖的效果。這個(gè) 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();
  }
});

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

相關(guān)文章

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

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

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

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

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

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

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

    JavaScript 中使用 Generator的方法

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

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

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

    深入淺析JS中的嚴(yán)格模式

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

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

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

    Js獲取當(dāng)前日期時(shí)間及格式化代碼

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

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

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

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

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

最新評(píng)論

安新县| 托克逊县| 玛多县| 独山县| 搜索| 阜城县| 门源| 中卫市| 贡嘎县| 博白县| 岚皋县| 台中县| 尚义县| 米脂县| 双流县| 普宁市| 延寿县| 长兴县| 鄯善县| 凯里市| 云阳县| 汉寿县| 深州市| 博白县| 五原县| 米易县| 台南县| 利川市| 石楼县| 电白县| 扎赉特旗| 赤水市| 政和县| 英吉沙县| 延津县| 花莲市| 邳州市| 新宁县| 临沧市| 宽城| 鸡东县|