1.什么是mxgraph

mxGraph是一个JavaScript图表库,可以快速创建交互式图形和图表应用程序,这些应用程序可以在其供应商支持的任何主要浏览器中运行。mxGraph 提供图形绘制、图形可视化、图形交互、图形布局、图形分析等能力, 适用于工作流程图、BPMN图、网络图、UML图、循环图、组织结构图、MindMap图、机架图、甘特图、信息图、平面图等绘制。
mxGraph在2005年创建,作为商业项目一直持续到2016年,2016年创建者以Apache 2.0开源协议在GitHub上公布源码。
官方产品(Draw.io): https://app.diagrams.net/
官方API :http://jgraph.github.io/mxgraph/docs/js-api
GitHub库:jgraph/mxgraph

1.1mxGraph 架构分析

mxGraph中有三个主要的组件:mxGraphmxGraphModelmxCell(含edge和vertex)。
mxGraph是用户直接操作的图,图的所有状态都保存;在mxGraphModel中,而图中的顶点和边都是用mxCell定义。三者层次关系如图所示:
当用户对mxGraph进行操作时,所有操作都映射到对mxGraphModel中保存的状态进行修改,而mxGraphModel中保存的状态也就是mxCell的状态。
围绕着这三个组件,mxGraph定义了很多属性,比如图的功能、mxGraphModel的持久化、mxCell的外观等等。此外mxGraph还具有非常强大的事务管理机制和事件监听器。

主要组件 描述 作用
mxClient mxClient.js是客户端的引导机制,此文件include了运行mxGraph所需的所有源文件,并加载了其依赖的资源文件,以及配置了客户端的语言。 设置加载相关文件的全局变量,设置相关路径,设置客户端语言,加载css文件和js文件
mxGraph mxGraph继承自mxEventSource以实现基于Web的图形组件的功能性方面。要激活平移和连接,使用setPanning和setConnectable,对于框线选择,必须创建一个新的mxRubberband实例。默认情况下,以下监听器添加到mouseListeners:tooltipHandler:显示工具提示的mxTooltipHandler,panningHandler:用于平移和弹出菜单的mxPanningHandler,connectionHandler:用于创建连接的mxConnectionHandler,graphHandler:用于移动和克隆cell的mxGraphHandler 如果启用了这些监听器,则将按上述顺序调用它们。
mxGraphModel mxGraphModel 是描述了图形结构的核心的模型,被称为mxGraphModel,可以在model包中发现。 另外,对图形结构的添加,更改和清除是通过图模型API来完成的。该模型还提供了方法来确定图形 的结构,以及提供方法来设置,如能见度、分组和样式的视觉状态。mxGraphModel是基本的对象,它存储着图形的数据结构。
mxCell mxCell是节点和连线的图元对象。mxCell从模型那里复制了许多的方法。它们的主要差别在于,使用模型的方法会创建相关的事件通知以及撤销方法

mxGraph的功能依赖关系如图所示:

除此之外,mxGraph 还有 mxClient、组结构、复杂管理等部分组成,并提供 editor、io、handler、shape、view、util、layout 等 API。具体框架结构如下。

其中 API 提供如下能力:
描述
editor 提供了实现图编辑器所需的类,主要的类是mxEditor
handler, layout, shape 分别包含事件监听器,布局算法和形状。图形事件监听器包括用于框线选择的mxRubberband,用于工具提示的mxTooltipHandler和用于基本单元修改的mxGraphHandler。mxCompactTreeLayout实现树形布局算法,shape包提供各种形状,这些形状是mxShape的子类。
view, model view和model实现了图形组件,由mxGraph表示。它指的是包含了mxCells并缓存mxGraphView中单元格的状态的mxGraphModel。根据mxStylesheet中定义的外观,使用mxCellRenderer绘制单元格。撤消历史记录在mxUndoManager中实现。要在图表上显示图标,可以使用mxCellOverlay。验证规则使用mxMultiplicity定义。
util 提供了实用程序类,包括用于复制粘贴的mxClipboard,用于键和样式表值的mxConstants,用于跨浏览器事件处理和通用功能的mxEvent和mxUtils,用于国际化的mxResource和mxLog用于控制台输出。
io 实现了一个通用的mxObjectCodec,用于将JavaScript对象转换为XML。主要类是mxCodec。mxCodecRegistry是自定义编解码器的全局注册表。

2.mxgraph初体验:

下面将基于vue框架,使用mxgraph绘制第一个流程图
第一步.安装mxgraph

npm install mxgraph-js --save

第二步.导入(在你需要用到的组件文件中导入):

import { mxGraph } from 'mxgraph-js'

第三步:开始使用:

<template><div ref="graph_container" class="graph_container"></div>
</template><script>
import { mxGraph } from 'mxgraph-js'
export default {name: 'HelloWorld',mounted () {// 创建画布var graph = new mxGraph(this.$refs.graph_container);var parent = graph.getDefaultParent();// 开始更新画布graph.getModel().beginUpdate();try {// 插入节点let v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);let v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);// 插入连线graph.insertEdge(parent, null, '', v1, v2);} finally {// 画布更新结束graph.getModel().endUpdate();}}
};
</script><style>
</style>

第四步:运行效果

API方法使用总结:
mxGraph.insertVertex(parent, id, value, x, y, width, height, style)
–在调用开始/结束更新中,创建并插入一个新的节点到模型中。
mxGraph.insertEdge(parent, id, value, source, target, style)
–在调用开始/结束更新中,创建并插入一条新的连线到模型中。
mxGraph.insertVertex()
–会创建一个mxCell对象并返回。

方法的参数:
parent – 组结构中此图元的直接父图元。我们会很快谈论到组结构,但现在我们直接使用graph.getDefaultParent();作为默认的父图元,就像在 HelloWorld 这个例子一样。
id – 描述此单元的全局唯一身份号码,总是一个字符串。主要用于外部对这单元的引用。如果你不想自己维护这些号码,只需要传入一个空参数并确保mxGraphModel.isCreateIds()返回真即可。这样,模型就会管理这些号码,并保证它们的唯一性。
value – 此单元的用户对象。用户对象只是一些对象,可以让您把应用程序的商务逻辑与mxGraph的可视化呈现相关联。在手册的后面有详细地描述,这里我们就只用字符 串就好,并把它们显示成节点和边的标签。
x, y, width, height – 就像名字提到的,这是节点的左上角的 x 和 y 的位置以及它的宽度和高度。
style – 将被应用到节点的样式描述。关于样式,很快会有更详细的描述,简单来讲,就是一个特定格式的字符串。这个字符串有零个或多个样式名字和一些键/值配对,用来覆盖全局设置或者创立新的样式。除非我们要创建自己的样式,我们可以直接使用这些现有的设置。
source和target –参数定义了节点要连接的节点;注意,源节点 和目标节点需要已经被加入到模型中。
注意:
1.mxGraph事物的更新(插入新元素时)一定要放在 beginUpdate 和 endUpdate 里面。一次 beginUpdate 必须对应一次 endUpdate
2.由于mxGraph配置了默认的样式(节点字体、连线等元素样式)和默认的配置所以样式看起来比较单一;我们可以在绘制图形前修改mxGraph默认配置好的配置项,来达到我们想要的效果;

3.mxgraph的自定义配置
js代码如下:

<template><div ref="graph_container" class="graph_container"></div>
</template><script>
import { mxGraph, mxRubberband, mxConstants, mxEvent, mxGraphHandler, mxEdgeStyle } from 'mxgraph-js'
export default {name: 'HelloWorld',mounted () {var graph = new mxGraph(this.$refs.graph_container); //创建视图graph.setHtmlLabels(true); // Label 将显示 Html 格式的 Valuegraph.setTolerance(20);graph.setEnabled(true); //设置启用,就是允不允许你改变CELL的形状内容。graph.setVertexLabelsMovable(true); // 允许移动 Vertex 的 Labelgraph.setConnectable(true); // 是否允许Cells通过其中部的连接点新建连接,false则通过连接线连接    graph.setDropEnabled(true); // 从工具栏拖动到目标细胞时细胞边界是否产生光圈    graph.setTooltips(true); // 是否显示提示,默认显示Cell的名称 graph.setResizeContainer(true); // 容器大小自适应graph.setMultigraph(false); // 重复连接graph.setAllowLoops(true); // 允许连线的目标和源是同一元素new mxRubberband(graph); // 左键框选(编辑状态下生效)// 节点样式var style = graph.getStylesheet().getDefaultVertexStyle();// style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_BOTTOM;//文字对齐方式// style[mxConstants.STYLE_FILLCOLOR] = 'rgb(251, 148, 79)'; //填充色style[mxConstants.STYLE_FONTSIZE] = 14; //文字大小style[mxConstants.STYLE_FONTCOLOR] = "#fff"; //文字颜色style[mxConstants.STYLE_WHITE_SPACE] = "wrap"; //自动换行delete style[mxConstants.STYLE_STROKECOLOR]; //去掉边框graph.getView().updateStyle = true; // 动态改变样式graph.setAutoSizeCells(true); // 鼠标拖动graph.setPanning(true); // 移动镜头(移动容器坐标轴)graph.panningHandler.useLeftButtonForPanning = true; // 设置左键可移动容器坐标轴graph.setCellsResizable(false); // 禁止改变元素大小mxEvent.disableContextMenu(this.$refs.graph_container); // 禁用浏览器默认的右键菜单栏graph.connectionHandler.setCreateTarget(true); // 是否创建目标mxGraphHandler.prototype.setMoveEnabled(false);//是否可以移动  mxGraphHandler.prototype.guidesEnabled = true;//显示细胞位置标尺  /*禁用节点双击,防止改变数据 */  graph.dblClick = function (evt, cell) { var model = graph.getModel(); if (model.isVertex(cell)) { return false; } };  //重写方法不允许那条线(edge)可以编辑    graph.isCellEditable = function (cell) { return !this.getModel().isEdge(cell) && !this.getModel().isVertex(cell); };// 鼠标滚轮缩放mxEvent.addMouseWheelListener(function (evt, up) {if (up) {graph.zoomIn();} else {graph.zoomOut();}mxEvent.consume(evt);});style = graph.getStylesheet().getDefaultEdgeStyle();style[mxConstants.STYLE_EDGE] = mxEdgeStyle.TopToBottom;style[mxConstants.STYLE_STROKECOLOR] = "rgb(115, 121, 133)"; //连接线颜色delete graph.getStylesheet().getDefaultEdgeStyle()["endArrow"]; //去掉箭头//绑定双击事件graph.addListener(mxEvent.DOUBLE_CLICK, function (sender, evt) {var cell = evt.getProperty("cell");console.log(cell)}); var parent = graph.getDefaultParent();graph.getModel().beginUpdate();// 开始画图try {// 插入节点var v1 = graph.insertVertex(parent, null, "Hello,", 20, 20, 80, 30); // 插入节点var v2 = graph.insertVertex(parent, null, "World!", 200, 150, 80, 30); graph.insertEdge(parent, null, " ", v2, v1); graph.insertEdge(parent, null, " ", v2, v2); } finally {graph.getModel().endUpdate();}}
};
</script><style >
</style>

注意:
1.我们在配置中会用到mxGraph中其他的模块,所以我们使用到mxGraph的哪个方法就得把它们import进来。
2.mxGraph中有三个主要的组件:mxGraph、mxGraphModel、mxCell。mxGraph是用户直接操作的图,图的所有状态都保存在mxGraphModel中,而图中的顶点和边都是用mxCell定义。
3.insertVertex 做了三件事,先是设置几何信息,然后创建一个节点,最后将这个节点添加到画布。insertEdge 与 insertVertex 类似,方法中的几何信息四个数字分别对应 X、 Y、 宽、 高 ;坐标是以graph的左上角为原点。
3.当用户对mxGraph进行操作时,所有操作都映射到对mxGraphModel中保存的状态进行修改,而mxGraphModel中保存的状态也就是mxCell的状态。
运行效果:

4.绘制具备树形结构的拓扑图
对于自动布局,我们可以根据官网提供的mxHierarchicalLayout模块,它提供了getLayout钩子。可以重写它以返回给定cell的子节点的布局算法。
代码如下:

<template><div ref="graph_container" class="graph_container"></div>
</template><script>
import { mxHierarchicalLayout, mxGraph, mxUtils } from 'mxgraph-js'export default {name: 'HelloWorld',mounted () {this.init()},methods: {init () {// 创建一个mxGraph 实例var graph = new mxGraph(this.$refs.graph_container);var model = graph.getModel();var parent = graph.getDefaultParent();var doc = mxUtils.createXmlDocument();// 创建userObjectvar uo1 = doc.createElement('person');uo1.setAttribute("firstName", 'Sponge');uo1.setAttribute("lastName", 'Bob')var uo2 = doc.createElement('person');uo2.setAttribute("firstName", "Super");uo2.setAttribute("lastName", 'Man');var uo3 = doc.createElement('person');uo3.setAttribute("firstName", "Good");uo3.setAttribute("lastName", 'Boy');var uo4 = doc.createElement('person');uo4.setAttribute("firstName", "Bad");uo4.setAttribute("lastName", 'Girl');// 定义convertValueSTotring方法graph.convertValueToString = function (cell) {if (mxUtils.isNode(cell.value)) {// 判断节点类型是否为'person'if (cell.value.nodeName == "person") {var firstName = cell.getAttribute("firstName", '');var lastName = cell.getAttribute("lastName", '');if (lastName != null && lastName.length > 0) {return lastName + '---' + firstName;}return firstName}}return '';};// 创建一个布局实例var layout = new mxHierarchicalLayout(graph)// var layout = new mxCircleLayout(graph,20)model.beginUpdate();try {// 绘制节点var child1 = graph.insertVertex(parent, null, uo1, 300, 100, 80, 30, 'fillColor=#3CAEA3;strokeColor = white;rounded=1;fontStyle=1');var child2 = graph.insertVertex(parent, null, uo2, 20, 20, 80, 30, 'fillColor=#3CAEA3;strokeColor = white;rounded=1;fontStyle=1');var child3 = graph.insertVertex(parent, null, uo3, 200, 150, 80, 30, 'fillColor=#3CAEA3;strokeColor = white;rounded=1;fontStyle=1');var child4 = graph.insertVertex(parent, null, uo4, 300, 150, 80, 30, 'fillColor=#3CAEA3;strokeColor = white;rounded=1;fontStyle=1');// 绘制连线graph.insertEdge(parent, null, '', child1, child2, 'strokeColor=#F6D55C');graph.insertEdge(parent, null, '', child1, child3, 'strokeColor=#F6D55C');graph.insertEdge(parent, null, '', child1, child4, 'strokeColor=#F6D55C');graph.insertEdge(parent, null, '', child2, child4, 'strokeColor=#F6D55C');layout.execute(parent)}finally {model.endUpdate()}}}
};
</script>
<style>
</style>

运行效果:

关于mxGraph,官方API文档不友好,介绍简单;API文档也是全是英文,官网的Demo倒是不少,不过有的拉下来在自己的环境下跑会报错,只有根据官方的demo不断地尝试和理解才能解决使用上的问题,目前只基本掌握基础使用部分,个人使用心得还会继续更新。
5.辅助功能演示:
通过以上三个demo的演示,相信大家对mxgraph已经有大致的了解了;下面在demo基础上我们针对一些辅助功能进行演示:
5.1选择线框

var rubberBand = new mxRubberband(graph);
注意:我们可以通过css来修改选择框的填充颜色;如:
.mxRubberband {background-color: rgb(58, 58, 207);
position: absolute;
}

 5.3修改连线样式
    mxEdgeStyle 中定义了线的各种样式:Loop、ElbowConnector、SideToSide等等,可以通过以下方式自定义连线样式:mxEdgeStyle.MyStyle = function(state, source, target, points, result){if (source != null && target != null){var pt = new mxPoint(target.getCenterX(), source.getCenterY());if (mxUtils.contains(source, pt.x, pt.y)){pt.y = source.y + source.height;}result.push(pt);}};mxStyleRegistry.putValue('myEdgeStyle', mxEdgeStyle.MyStyle);var e1 = graph.insertEdge(parent, null, '连线', v1, v2);
graph.getModel().setStyle(e1, 'edgeStyle=myEdgeStyle');

也可以在定义好自定义样式后,直接修改连线的默认样式:

var style = graph.getStylesheet().getDefaultEdgeStyle();
style[mxConstants.STYLE_EDGE] = mxEdgeStyle.MyStyle;

5.4开起“指引”功能

mxGraphHandler.prototype.guidesEnabled = true;

可以通过以上代码开起“指引”功能,即在拖动节点时会有对齐线等提示效果

关于mxGraph,由于官方API文档是全英文的,而且介绍简单;,官网的Demo倒是不少,但是官方Demo在自己的环境下跑会报错,只有根据官方的demo不断地尝试和理解才能解决使用上的问题,目前只基本掌握基础使用,后续会着重补充针对API的使用总结。

5.5 鼠标划过节点或连线时;边框高亮显示

可以通过以上代码添加对线和节点在鼠标划过时的高亮效果。mxCellTracker(graph, color, funct) 的第三个参数是可选的,如果设置了funct则需要在此函数中重写getCell逻辑。

针对上述功能,我们下一步进行mxgraph拓扑图编辑工具的开发说明:
初始化画布:
导入mxgraph的资源的由于源代码中已有且各个功能注释已写的较明确在这里就暂不赘述了,主要以功能性方面进行介绍;下面将初始化画布分解为6个步骤讲解
第一步:首先mxgraph将会检测当前浏览器是否支持mxgraph,若不支持将会弹出警告并终止操作
第二步:.创建画布:

// 创建画布并进行初始化
createGraph () {// 创建graph// 方式一:直接构建graph实例// this.graph = new mxGraph(this.$refs.container)// eslint-disable-next-line new-capthis.editor = new mxEditor()this.graph = this.editor.graphthis.editor.setGraphContainer(this.$refs.container)......//其他配置项
}

我们在获取画布的dom元素(this.$ref.container)之后即可进行初始化;此步骤相当于告诉mxgraph我们将在那个dom元素上进行绘图;剩下的就是画布的配置项,各个配置的具体功能代码中备注
第三步:配置事件中心:此步骤将会配置各个事件
3.1监听 新增 cell 事件:
(在mxgraph中,节点和连线都是cell),当我们向画布新增cell时就会触发该事件;我们还可以配置其他的事件,所有事件都在mxEvent中,直接在控制台打印出,mxEvent就可以知道有什么事件,配置方法直接参考 ADD_CELLS 即可
第四步:配置鼠标事件:
我们可以配置鼠标事件来监听我们鼠标在画布中的操作

 // 配置鼠标在画布中的事件configMouseEvent () {this.graph.addMouseListener({// currentState: null,// previousStyle: null,mouseDown: (sender, evt) => {if (!evt.state) {console.log('点击了画布')} else if (evt.state.cell.edge) {console.log('点击了连线', evt.state.cell)}},mouseMove: (sender, me) => {// this.graphX = Math.ceil(me.graphX)// this.graphY = Math.ceil(me.graphY)},mouseUp: (sender, evt) => {if (evt.sourceState === undefined) {return false} else {var cell = evt.sourceState.cellif (cell) {if (cell.edge && cell.edge === true) {// 点击的是连线localStorage.setItem('currOptEdgeId', cell.id)} else if (cell.vertex && cell.vertex === true) {// 点击的是节点localStorage.setItem('currOptInstId', cell.id)} else {// 点击的是其他元素console.log('点击了其他元素')}} else {this.$message.error('请选择节点或者连线')}}}})},

各个事件函数的形参即可获取当前鼠标操作的元素信息
第五步:.配置画布中的右键菜单
首先mxEvent.disableContextMenu(this.$refs.container) 告诉mxgraph你要在画布中配置右键菜单,并使用 popupMenuHandler 进行菜单项新增

graph.popupMenuHandler.factoryMethod = (menu) => {menu.addItem('菜单名称', null, () => {})
}// 配置右键菜单栏
configMenu () {// 禁用浏览器默认的右键菜单栏mxEvent.disableContextMenu(this.$refs.container)this.graph.popupMenuHandler.factoryMethod = (menu) => {menu.addItem('输出所有节点', null, () => {Object.values(this.graph.getModel().cells).forEach((cell) => {console.log(cell)})})menu.addSeparator()menu.addItem('全选', null, () => {this.graph.selectAll()})menu.addItem('选中所有节点', null, () => {this.graph.selectCells(true, false)})menu.addItem('选中所有连线', null, () => {this.graph.selectCells(false, true)})
}

第六步:.初始化左侧工具栏:
此处是重点,在此处配置后左侧的节点列表即可进行拖拽,并可通过拖拽节点到画布新增节点

// 初始化基础节点initGeneralTool () {var generalToolbarDomArray = this.$refs.generalToolItems// 判断是否为数组且数组是否为空if (!(generalToolbarDomArray instanceof Array || generalToolbarDomArray.length <= 0)) {return}generalToolbarDomArray.forEach((dom, domIndex) => {var toolItem = this.generalToolbarItemsView[domIndex]var { width, height } = toolItemvar itemClass = (toolItem.class)// 新增基础节点var generalDropHandler = (graph, evt, dropCell, x, y) => {this.addByDrag = trueconst drop = !R.isNil(dropCell)const realX = drop ? x - dropCell.geometry.x : xconst realY = drop ? y - dropCell.geometry.y : yconst { width, height } = toolItemconst style = `shape=ellipse;fillColor=${this.colorMapping[toolItem['entity_class']['entity_type']]};`const parent = drop ? dropCell : this.graph.getDefaultParent()this.graph.getModel().beginUpdate()try {let vertex = this.graph.insertVertex(parent, null, null, realX - (width / 2), realY - (height / 2), width, height, style)vertex.value = toolItem['entity_class']['entity_name']vertex.id = this.get_uuid()vertex.instanceClassInfo = toolItemlocalStorage.setItem('currOptInstId', vertex.id)} finally {this.graph.getModel().endUpdate()}}// 设置节点被拖拽时的样式(预览)var generalcreateDragPreview = () => {var elt = document.createElement('div')elt.style.width = `${width}px`elt.style.height = `${height}px`elt.style.transform = 'translate(-50%,-50%)'elt.style.backgroundColor = toolItem.instanceColorelt.style.lineHeight = `${height}px`elt.style.color = `#ffff`elt.style.textAlign = `center`elt.className = itemClasselt.textContent = toolItem['entity_class']['entity_name']return elt}// 允许拖拽let ds = mxUtils.makeDraggable(dom, this.graph, generalDropHandler, generalcreateDragPreview(), 0, 0, true, true)ds.setGuidesEnabled(true)})},

6.1首先获取左侧所有节点的dom,generalToolbarDomArray 这里有所有节点的样式和节点信息,

获取后遍历所有节点绑定generalcreateDragPreview , generalDropHandler , makeDraggable函数

var generalToolbarDomArray = this.$refs.generalToolItems

6.2当每次将左侧的节点拖拽时就会自动执行generalcreateDragPreview,此函数实现左侧节点被拖拽时的样式预览;

6.3当节点拖拽至画布并松开后会执行generalDropHandler

6.4当节点新增到画布之后会自动触发 ADD_CELLS 事件

注意:
左侧节点列表上方的搜索功能.在执行搜索后 generalToolbarDomArray 会改变, 所以在过滤完节点列表之后 我们要手动再执行一遍 initGeneralTool 函数,这样新的节点列表才可被拖拽新增

第七步:.自动布局
mxgraph提供了几种自动布局的API,直接调用graphLayout即可

// 布局graphLayout (animate, layoutType) {this.graph.getModel().beginUpdate()try {if (layoutType === 'randomLayout') {// 随机布局mxFastOrganicLayout.prototype.minDistanceLimit = 100// eslint-disable-next-line new-capvar layout = new mxFastOrganicLayout(this.graph)layout.forceConstant = 500layout.execute(this.graph.getDefaultParent())} else if (layoutType === 'hierarchicalLayout') {// 分层布局mxHierarchicalLayout.prototype.intraCellSpacing = 300mxHierarchicalLayout.prototype.fineTuning = falsemxHierarchicalLayout.prototype.traverseAncestors = falsemxHierarchicalLayout.prototype.resizeParent = true// 无关系实体之间的间距mxHierarchicalLayout.prototype.interHierarchySpacing = 200// 层级之间的距离mxHierarchicalLayout.prototype.interRankCellSpacing = 800// eslint-disable-next-line new-capvar hierarchicallayout = new mxHierarchicalLayout(this.graph, mxConstants.DIRECTION_NORTH)hierarchicallayout.execute(this.graph.getDefaultParent())} else if (layoutType === 'compactTreeLayout') {// 树形布局// eslint-disable-next-line new-capvar compactTreelayout = new mxCompactTreeLayout(this.graph)compactTreelayout.execute(this.graph.getDefaultParent())} else if (layoutType === 'circleLayout') {// 圆形布局// eslint-disable-next-line new-capvar circleLayout = new mxCircleLayout(this.graph, 400)circleLayout.execute(this.graph.getDefaultParent())}} catch (e) {throw e} finally {// 是否开启布局动画if (animate) {// eslint-disable-next-line new-capvar morph = new mxMorphing(this.graph, 20, 7.7, 40)morph.addListener(mxEvent.DONE, () => {this.graph.getModel().endUpdate()})morph.startAnimation()} else {this.graph.getModel().endUpdate()}}

项目源码欢迎star:

项目源码地址:

推荐文章:

1.基于mxGraph的可视化环境组网设计器:https://github.com/igonglei/env-editor
2.mxGraph学习笔记:https://www.kancloud.cn/wujie520303/mxgraph/1434409
3.功能全面的案例:https://github.com/lanniu/vue-mxgraph-example
4.关于mxGraph可搜索的API中文文档:https://api.mxgraph.lanniu.top/#/

Vue中使用mxgraph开发流程图工具相关推荐

  1. vue中使用bpmn-js绘制流程图,并实现汉化、自定义Palette及ContextPad。

    一.认识bpmn-is bpmn-js是一个BPMN2.0渲染工具包和web建模器, 使得画流程图的功能在前端来完成. 效果图如下(改造后): 二.在vue基本使用 安装bpmn-js npm ins ...

  2. vue中使用openlayers开发离线地图

    最近在使用openlayers开发离线地图,但是全英文的文档属实有点难顶,本文代码主要就是实现marker点位标记以及点击图标会显示弹窗,参考博客写的非常的详细也是我找到比较好的. 文中用到的瓦片地图 ...

  3. Vue中的Pinia状态管理工具 | 一篇文章教会你全部使用细节

    文章目录 Pinia状态管理 Pinia和Vuex的对比 Pinia基本使用

  4. MxGraph从入门到精通之5:在Vue项目中使用MxGraph

    第一步:安装npm包 npm install mxgraph 第二步:在mxgraph.vue中使用mxgraph <template><div><div ref=&qu ...

  5. web 流程图工具_Web技术在云剪辑工具中的技术实践

    云剪辑是集视频制作.生产.分发等为一体的在线视频制作平台,具备工具及服务两方面能力:工具方面,云剪辑具备全面视频剪辑能力,相比行业中其他在线剪辑工具能力更强大,支持范围包括多轨道音视频合成.音视频素材 ...

  6. Vue CLI 3.0 正式发布,Vue.js 开发标准化工具

    Vue CLI 3.0 已发布,该版本经历了重构,旨在: 减少现代前端工具的配置烦扰,尤其是在将多个工具混合在一起使用时: 尽可能在工具链中加入最佳实践,让它成为任意 Vue 应用程序的默认实践. V ...

  7. 计算机英语介绍项目,【精品文档】614关于计算机专业Vue.js应用程序设计开发介绍简介概述的毕业设计论文英文英语外文文献翻译成品资料:了解Vue.js项目和工具(中英文双语对照)...

    1.本文是中英对照毕业设计论文外文文献翻译,下载后直接可用!省去您找文献.pdf整理成word以及翻译的时间,一辈子也就一次的事!文献引用作者出处信息:Freeman, Adam Pro Vue.js ...

  8. 在vue项目中引用vuex状态管理工具

    在vue项目中引用vuex状态管理工具 一.vuex是什么? 二.使用步骤 1.引入库 2.在main.js文件引入配置 3.配置store/index.js文件 4.获取state数据 5.获取ge ...

  9. 基于VUE和JSPlumb的在线绘制流程图工具

    基于VUE和JSPlumb的在线绘制流程图工具 介绍 VUE FLOW DESIGN流程设计器,基于Vue + Ant Design Vue + JSPlumb,该组件目的是为了使用在Vue项目中,它 ...

最新文章

  1. Android学习书籍参考
  2. 用计算机创造的音乐,计算机音乐创作(普通组)
  3. linux下使用gcp拷贝数据的时候显示进度条
  4. 深度学习问题解决:Check failed: stream-parent()-GetConvolveAlgorithms( conv_parameters.ShouldIncludeWinogra
  5. poj3253 优先队列
  6. 洛谷P2746 [USACO5.3]校园网Network of Schools
  7. 阿里云将增设马来西亚数据中心 中国技术获赞
  8. idea+maven下jrebel的安装破解
  9. python treeview文本自动换行显示_在tkinter.ttk.Treeview列中设置文本格式
  10. 前端架构设计1:代码核心
  11. PowerShell遍历文件夹下的子文件夹和文件
  12. 演练 构造函数的显示调用与隐式调用 c# 1613715344
  13. 洞仙歌·冰肌玉骨 [宋] 苏轼
  14. python selenium环境安装及配置_selenium环境配置
  15. Industrial Style Transfer with Large-scale Geometric Warping and Content Preservation论文解读
  16. Ubuntu系统如何进行屏幕截图
  17. LSD(线段检测测试文件)
  18. android l m8,搭Android L HTC M8曝新系统截图
  19. Netty空闲检测之写空闲
  20. 给应届毕业生的建议:萌新程序员找工作的三板斧

热门文章

  1. js删除对象中所有值为null和undefined的属性
  2. 大众点评店铺详情页评论采集(破解css文字映射反爬,包含项目github 可用时间至2020-01-21)
  3. 【Python】python链表
  4. 服务器存储(基础概念及历史)
  5. java中换行符_Java 中的空格符、换行符等怎么表示
  6. 计算机长期不用无法开机,电脑长时间不用开机进不了系统怎么办
  7. java输出彼此用一个逗号隔开
  8. 常见Python自动化测试面试题(含答案)建议收藏!
  9. 数据库“写时模式”与“读时模式”对比
  10. 服务器suse11修改root密码,suse更改root密码(示例代码)