mxGraph入门

标签: Javascript 分类: Javascript 创建时间:2020-07-29 02:12:36 更新时间:2024-11-15 10:49:44

从别人系统里,发现了一个很牛逼的功能,就是流程图,刚开始我以为是使用的openlayers或者是leaflet,后来怎么也找不到,最后确定了是使用了mxGraph,所谓绘制的拓扑图,其实就是流程图罢了。类似的插件还有dagre-d3,有没有前端好用的画流程图的组件? 绘制流程图的开源讨论,还有GGEditor,这里还有其他的几个插件的对比,draw.io、aworkflow.js、flowchart.js、mermaidjs等等,最近又添加了一个 乐吾乐 的拓扑图绘制功能。

其实也挺简单的,就是引入js文件和src目录,然后就是编写函数。,当然也可以结合vue进行开发。

参考文章:
1.mxGraph教程 (这是我参考的第一篇入门文章)
2.MXgraph用户手册-JavaScript客户端 (入门文章,好像是官网的中文翻译)
3.mxGraph 入门实例教程 (入门文章)
4.mxgraph 架构分析与 mxgraph-editor 编辑器开发 (一个人的blog,在mxgrap的基础上,拓展成了mxgraph-editor)
5.mxgraph的艰难入门 (这个对官网提供的几个例子进行了分别描述)
6.mxGraph User Manual – JavaScript Client (官网的用户手册)
7.mxgraph初体验 (这篇文章还讲了后台java的解析和mxGraph在vue中使用的若干问题)
8.JGraph (JGraph specialises in browser-based diagramming components and applications.JGraph专门研究基于浏览器的图表组件和应用程序)

1.编辑器

可以使用在线编辑器进行流程图的绘制和编辑,Graph Editor,可以使用菜单栏中的Extras->Edit Diagram,打开编辑框,然后查看已经生成的xml文件,然后进行复制,这样就可以实现编辑xml然后保存了。

参考文章:
1.mxgraph 架构分析与 mxgraph-editor 编辑器开发 (这里讲了如何实现编辑器)
2.Graph Editor (在线编辑软件,但是已经不能导出xml文件了,不能导出xml文件了)
3.korbinzhao/mxgraph-editor (一个开源的xml编辑器,不过好像star很少,这个仓库也就是)

改造mxgraph-editor

korbinzhao/mxgraph-editor感觉已经不再维护了,所以你从github上下载下载来,运行就回报错primordials is not defined,需要以下两步
(1) 需要修改package.json,中的gulp版本为:”gulp”: “^4.0.2”

(2) 修改工程目录下的gulpfile.js,将任务使用gulp4的语法重写一遍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const gulp = require('gulp');
const less = require('gulp-less');
const postcss = require('gulp-postcss');
const sourcemaps = require('gulp-sourcemaps');
const autoprefixer = require('autoprefixer');
const replace = require('gulp-replace');

gulp.task('less', () => gulp.src('src/*.less')
.pipe(less())
.pipe(gulp.dest('lib')));

gulp.task('autoprefixer', () => gulp.src('src/*.css')
.pipe(sourcemaps.init())
.pipe(postcss([autoprefixer()]))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('./lib')));

// 旧代码
// gulp.task('replace', () => {
// gulp.src('lib/*.js')
// .pipe(replace(/\/(.+)\.less/, '/$1.css'))
// .pipe(replace(/\/(.+)\.styl/, '/$1.css'))
// .pipe(gulp.dest('lib'));
// });

// 新代码
gulp.task('replace', () => {
return gulp.src('lib/*.js')
.pipe(replace(/\/(.+)\.less/, '/$1.css'))
.pipe(replace(/\/(.+)\.styl/, '/$1.css'))
.pipe(gulp.dest('lib'));
});

// 旧的代码
// gulp.task('default', ['less', 'autoprefixer', 'replace']);


// 新的代码
gulp.task('default', gulp.series('less', 'autoprefixer', 'replace'));

2.鼠标放大所小

下面两个文章其实是一样的,无所谓谁抄谁的了。

3.整体移动

通过设置属性,可以实现图形的整体移动

1
2
3
4
5
6
7
8
9
10
11
12
// 整体移动,不改变节点连线的坐标,类似于改变观看位置。
// 鼠标拖拉,手机浏览器拖拉
graph.setPanning(true);

// 可能不支持部分包含web页面的控件

// 如果不支持添加下面这个
graph.panningHandler.useLeftButtonForPanning = false;
mxPanningHandler.prototype.isPanningTrigger = function(me) {
var evt = me.getEvent();
return true;
};
参考文章:
1.mxGraph 拓扑图插件 (这篇文章有些属性的配置)
2.mxGraph 如何实现图形拖动 (这里讲了原理)
3.mxgraph一些常用方法

4.绘制菱形

参考文章:
1.javascript - 使用IE 10兼容模式使用Mxgraph旋转单元
2.mxgraph入门 之 mxcell的操作方法
3.mxgraph上手实践 (这篇文章也算是个入门,还有一些常用的方法,绘制菱形、方块等。)
4.mxgraph 之 节点样式设置 (这篇文章写的有点简陋,但是好像是使用的xml配置的样式)
5.mxgraph 系列【3】: 底层状态树 mxCell (这篇文章有关于菱形的绘制过程,以及如何通过继承mxShape实现自定义图形,还有通过使用stencils接口定义新的图形,在我看到的项目中,确实有通过这种方式进行自定义图形的。)

5.修改内容

获取到相应的Cell,然后修改cell.value,然后刷新graph.refresh()

6.其他的文章

1.API Specification (官网的API参考)

7.vue中使用mxGraph

可以参考参考文章1,编写自己的引入函数index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import mx from 'mxgraph';
const mxgraph = mx({
mxImageBasePath: process.env.VUE_APP_BASE_URL+'/lib/mxGraph/src/images',
mxBasePath: process.env.VUE_APP_BASE_URL+'/lib/mxGraph/src'
});

let mxStencilRegistry=mxgraph.mxStencilRegistry;
let mxStencil=mxgraph.mxStencil;
let mxConstants=mxgraph.mxConstants;
let mxUtils=mxgraph.mxUtils;

/**
* 扩展mxStencilRegistry,加载模型
*/
mxStencilRegistry.packages = [];
// Extends the default stencil registry to add dynamic loading
mxStencilRegistry.getStencil = function(name)
{
var result = mxStencilRegistry.stencils[name];
if (result == null)
{
var basename = mxStencilRegistry.getBasenameForStencil(name);
if (basename != null)
{
mxStencilRegistry.loadStencilSet(process.env.VUE_APP_BASE_URL+'/xml/stencils/' + basename + '.xml', null);
result = mxStencilRegistry.stencils[name];
}
}

return result;
};

mxStencilRegistry.getBasenameForStencil = function(name)
{
var parts = name.split('.');
var tmp = null;
if (parts.length > 0 && parts[0] == 'mxgraph')
{
tmp = parts[1];

for (var i = 2; i < parts.length - 1; i++)
{
tmp += '/' + parts[i];
}
}

return tmp;
};

// Loads the given stencil set
mxStencilRegistry.loadStencilSet = function(stencilFile, postStencilLoad, force)
{
force = (force != null) ? force : false;

// Uses additional cache for detecting previous load attempts
var installed = mxStencilRegistry.packages[stencilFile] != null;

if (force || !installed)
{
mxStencilRegistry.packages[stencilFile] = 1;
var req = mxUtils.load(stencilFile);
mxStencilRegistry.parseStencilSet(req.getXml(), postStencilLoad, !installed);
}
};

// Parses the given stencil set
mxStencilRegistry.parseStencilSet = function(xmlDocument, postStencilLoad, install)
{
install = (install != null) ? install : true;
var root = xmlDocument.documentElement;
var shape = root.firstChild;
var packageName = '';
var name = root.getAttribute('name');

if (name != null)
{
packageName = name + '.';
}

while (shape != null)
{
if (shape.nodeType == mxConstants.NODETYPE_ELEMENT)
{
name = shape.getAttribute('name');

if (name != null)
{
var w = shape.getAttribute('w');
var h = shape.getAttribute('h');

w = (w == null) ? 80 : parseInt(w, 10);
h = (h == null) ? 80 : parseInt(h, 10);

packageName = packageName.toLowerCase();
var stencilName = name.replace(/ /g,"_");

if (install)
{
mxStencilRegistry.addStencil(packageName + stencilName.toLowerCase(), new mxStencil(shape));
}

if (postStencilLoad != null)
{
postStencilLoad(packageName, stencilName, name, w, h);
}
}
}

shape = shape.nextSibling;
}
};
Object.keys(mxgraph).forEach((key)=>{
window[key] = mxgraph[key]
});

export default mxgraph;
参考文章:
1.vue中使用mxgraph (这里是基础的改造,但是有一个问题,就是在创建windows对象上,不能这么做)
2.vue-mxgraph报错 : 改变连接线的形状后会报错: Illegal constructor (这里解决了Illegal constructor的报错问题)
3.ekoz/vue-mxgraph-samples (一个使用vue加载mxgraph的例子)
4.拖拽画图库 mxGraph 的研究笔记 (其实是Graph Editor的一个笔记,对部分的结构内容也有说明,可以作为参考)
小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。