JointJS:JavaScript 流程图绘制框架

目录

  • 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  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" 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

时间: 2024-08-03 02:59:22

JointJS:JavaScript 流程图绘制框架的相关文章

atitit..代码生成流程图 流程图绘制解决方案 java &#160;c#.net &#160;php v2

atitit..代码生成流程图 流程图绘制解决方案 java  c#.net  php v2 1.1. Markdown 推荐,就是代码和flow都不能直接使用.1 1.2. Java code2flow 推荐,最起码代码能用,flow能看1 2. visus1211 3. 别的工具cvf 跟autoflowchart2 3.1. Code Visual 代码编辑器(code visual to flowchart v6.0) 推荐3 3.2. Axure不推荐,二进制的4 4. 参考4 1.1

【JavaScript】对比12 款优秀的JavaScript MVC/MVVC框架 你最喜欢Backbone or Ember

http://codebrief.com/2012/01/the-top-10-javascript-mvc-frameworks-reviewed/ 目前基本所以后台程序都是面向对象MVC模式开发,作为Web前端开发的人来说,也是很需要的,那么目前有没有可以借鉴的呢?作者(Gordon L.Hempton)一直在寻求哪种MVC框架最为完美,他将目前能获取到的所有框架都粗略地试了试,然后在文章中列出了每一种框架的情况概要,在文末分享了作者经过对比之后最终的推荐产品. 首先要特别说明一下,作者认为

CSS+Javascript的那些框架

CSS CSS 制作框架 SASS http://www.oschina.net/p/sass Blueprint  http://www.oschina.net/p/blueprintcss Elastic CSS布局  http://www.oschina.net/p/elastic CSS 预处理器 Stylus CSS预处理器 http://www.oschina.net/p/stylus LESS  CSS预处理 http://www.oschina.net/p/lesscss Web

JavaScript跳出iframe框架

一.window.top top属性返回最顶层的先辈窗口. 该属性返回对一个顶级窗口的只读引用.如果窗口本身就是一个顶级窗口,top属性存放对窗口自身的引用.如果窗口是一个框架,那么top属性引用包含框架的顶层窗口. 二.window.self self属性可返回对窗口自身的只读引用.等价于Window属性. 三.window.location window.location(MDN)对象用于获得当前页面的地址 (URL),并把浏览器重定向到新的页面. 3.1 示例 window.locatio

流程图绘制控件WpfDiagram

WpfDiagram是一款功能强大的流程图绘制控件,可以绘制工作流程图.对象层次和关系图.网络拓扑图.实体关系图.IVR.工业自动化.genealogy trees .算法流程图.组织结构图.XML文档.类图等.杰出的功能.稳定的性能以及优雅的架构使它成为迄今为止MindFusion中最高级的编程控制组件.它是我们在控件开发中的顶尖体验,该开发结合了.NET平台提供的最新一代的图表展示工具.因此,编程过程变得更加简单快捷,最终的图表变得更加具有吸引力并更加生动 具体功能: 软件的再分配完全免费

流程图绘制的方法和技巧

流程图基本认识 流程由一系列相互关联或相互作用的活动所组成,它是一系列将输入转换为输出,并实现增值的过程.企业流程的本质是以顾客为中心,从顾客的需求为出发点,来安排企业的生产经营活动. 流程图的分类: 什么样的流程图需要管理? 流程图绘制步骤; 1.绘制流程图借助辅助工具会很方便,打开迅捷画图在线网站,进入网站中,在首页点击进入迅捷画图: 2.这时会跳转到另一个页面,这里我们讲述的是流程图,在新建文件夹里面选择流程图: 3.点击流程图之后就会跳转到流程图制作页面: 4.在面板的四周我们可以看到很

Web流程图绘制使用raphael

林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文要实现一个流程图的绘制,最终的目标是实现流程图的自动绘制,并可进行操作,直接点击流程图上对应的方框就可以让后台跑相应的程序. 一.插件介绍 1.图形绘制raphael 其中图形绘制使用了raphael,下载地址:http://raphaeljs.com,它的功能非常强大. 中文帮助教程:http://html5css3webapp.com/raphaelApi.htm#Paper.

100 行代码实现的 JavaScript MVC 样式框架

介绍 使用过 JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用户界面,前端)中mvc的工作机理.这些框架实现了MVC,使得在一个单页面中实现根据需要变化视图时更加轻松,而模型-视图-控制器(mvc)的核心概念就是:处理传入请求的控制器.显示信息的视图.表示业务规则和数据访问的模型. 因此,当需要创建这样一个需要在单个页面中实现切换出不同内容的应用时,我们通常选择使用上述框架之一.但是,如果我们仅仅需要一个在一个url中实现视图切换的框架

用HTML5构建一个流程图绘制工具

在我们的开发工程中经常会使用到各种图,所谓的图就是由节点和节点之间的连接所形成的系统,数学上专门有一个分支叫图论(Graph Theroy).利用图我们可以做很多工具,比如思维导图,流程图,状态机,组织架构图,等等.今天我要做的是用开源的HTML5工具来快速构造一个做图的工具. 工具选择 预先善其事,必先利其器.第一件事是选择一件合适的工具,开源时代,程序员还是很幸福的,选择很多. flowchart.js  http://adrai.github.io/flowchart.js/ , 基于SV