mxgraph初体验
最近公司讓學(xué)習(xí)了mxgraph,簡(jiǎn)單總結(jié)一下
(1)mxGraph學(xué)習(xí)路徑
1)API:http://jgraph.github.io/mxgraph/docs/js-api/files/index-txt.html
2)demo:http://jgraph.github.io/mxgraph/javascript/index.html
(2)最簡(jiǎn)單的例子(helloword)
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Hello World</title><style>html, body {height: 100%;}#graphContainer {position: relative;overflow: hidden;width: 100%;height: 100%;background: url('./images/grid.gif');cursor: default;}</style> </head><body onload="main(document.getElementById('graphContainer'))"> <div id="graphContainer"></div> </body><script> const mxBasePath = '../static/mxgraph'; </script><script src="../mxClient.js"></script> <script> function main(container) {// 禁用鼠標(biāo)右鍵 mxEvent.disableContextMenu(container);const graph = new mxGraph(container);// 設(shè)置這個(gè)屬性后節(jié)點(diǎn)之間才可以連接 graph.setConnectable(true);// 開啟區(qū)域選擇new mxRubberband(graph);const parent = graph.getDefaultParent();graph.getModel().beginUpdate();try {const v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);//創(chuàng)建第一個(gè)節(jié)點(diǎn) const v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);//創(chuàng)建第二個(gè)節(jié)點(diǎn) const e1 = graph.insertEdge(parent, null, '30%', v1, v2);//創(chuàng)建連線 } finally {graph.getModel().endUpdate();} } </script> </html>?圖:
(3)mxGraph將圖轉(zhuǎn)換成xml字符串
var graph = new mxGraph(container); var xml = mxUtils.getXml(new mxCodec().encode(graph.getModel())) ; console.log(xml)如下,左圖可得右XML
(4)Java后臺(tái)解析xml
package org.sxdata.jingwei.util.transUtil;import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID;import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException;import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList;/*** @author sonyan* @version 2019年8月14日 下午3:09:15* @desc*/ public class DocumentUtil {private static String xmlStr = "";private static List<Map<String, Object>> nodeMapList = new ArrayList<Map<String, Object>>();/*** 將指定的document解析成xml字符串* @param doc* @return*/public static String getXmlStrByDocument(Document doc) {xmlStr = "";// 根節(jié)點(diǎn)名稱String rootName = doc.getDocumentElement().getTagName();// 遞歸解析ElementElement element = doc.getDocumentElement();return getElementStr(element);}/*** 將指定的節(jié)點(diǎn)解析成xml字符串* @param element* @return*/public static String getElementStr(Element element) {String TagName = element.getTagName();boolean flag = true;xmlStr = xmlStr + "<" + TagName;NamedNodeMap attris = element.getAttributes();for (int i = 0; i < attris.getLength(); i++) {Attr attr = (Attr) attris.item(i);xmlStr = xmlStr + " " + attr.getName() + "=\"" + attr.getValue() + "\"";}xmlStr = xmlStr + ">" ;NodeList nodeList = element.getChildNodes();Node childNode;for (int temp = 0; temp < nodeList.getLength(); temp++) {childNode = nodeList.item(temp);// 判斷是否屬于節(jié)點(diǎn)if (childNode.getNodeType() == Node.ELEMENT_NODE) {// 判斷是否還有子節(jié)點(diǎn) getElementStr((Element) childNode);if (childNode.getNodeType() != Node.COMMENT_NODE) {xmlStr = xmlStr + childNode.getTextContent();}}}xmlStr = xmlStr + "</" + element.getTagName() + ">";return xmlStr;}/*** 解析節(jié)點(diǎn)* @param element* @param graphId 所屬圖的id*/public static void parseElement(Element element, String graphId) {NodeList nodeList = element.getChildNodes();Node childNode;for (int temp = 0; temp < nodeList.getLength(); temp++) {childNode = nodeList.item(temp);String id= getUUID32();String nodeId = getNodeAttrValue(childNode, "id");if (!"0".equals(nodeId) && !"1".equals(nodeId) && "mxCell".equals(childNode.getNodeName())) {System.out.println(childNode.getNodeName());System.out.println("graphid:" + graphId);System.out.println("nodeId:" + getNodeAttrValue(childNode, "id"));System.out.println("parent:" + getNodeAttrValue(childNode, "parent"));System.out.println("value:" + getNodeAttrValue(childNode, "value"));System.out.println("source:" + getNodeAttrValue(childNode, "source"));System.out.println("target:" + getNodeAttrValue(childNode, "target"));System.out.println("vertex:" + getNodeAttrValue(childNode, "vertex"));System.out.println("edge:" + getNodeAttrValue(childNode, "edge"));parseElement2((Element) childNode, nodeId,graphId);System.out.println("****end*****");Map<String, Object> node = new HashMap<String, Object>();node.put("id", id);node.put("nodeId", nodeId);node.put("graphId", graphId);node.put("parent", getNodeAttrValue(childNode, "parent"));node.put("nodeValue", getNodeAttrValue(childNode, "value"));node.put("source", getNodeAttrValue(childNode, "source"));node.put("target", getNodeAttrValue(childNode, "target"));node.put("edge", getNodeAttrValue(childNode, "edge"));node.put("vertex", getNodeAttrValue(childNode, "vertex"));node.put("style", getNodeAttrValue(childNode, "style"));node.put("ass", getNodeAttrValue(childNode, "as"));node.put("nodeName", childNode.getNodeName());nodeMapList.add(node);}// 判斷是否屬于節(jié)點(diǎn)if (childNode.getNodeType() == Node.ELEMENT_NODE) {// 判斷是否還有子節(jié)點(diǎn) parseElement((Element) childNode, graphId);}}}/*** 解析mxGeometry節(jié)點(diǎn)* @param element * @param parentId * @param graphId*/private static void parseElement2(Element element, String parentId, String graphId) {NodeList nodeList = element.getChildNodes();Node childNode;for (int temp = 0; temp < nodeList.getLength(); temp++) {childNode = nodeList.item(temp);String nodeName = childNode.getNodeName();if ("mxGeometry".equals(nodeName)) {String nodeId = getNodeAttrValue(childNode, "id");String id = getUUID32();System.out.println("--name:" + nodeName);System.out.println("--height:" + getNodeAttrValue(childNode, "height"));System.out.println("--width:" + getNodeAttrValue(childNode, "height"));System.out.println("--x:" + getNodeAttrValue(childNode, "x"));System.out.println("--y:" + getNodeAttrValue(childNode, "y"));System.out.println("--as:" + getNodeAttrValue(childNode, "as"));System.out.println("--relative:" + getNodeAttrValue(childNode, "relative"));Map<String, Object> node = new HashMap<String, Object>();node.put("id", id);node.put("nodeId", nodeId);node.put("parent", parentId);node.put("nodeName", childNode.getNodeName());node.put("height", getNodeAttrValue(childNode, "height"));node.put("width", getNodeAttrValue(childNode, "width"));node.put("x", getNodeAttrValue(childNode, "x"));node.put("y", getNodeAttrValue(childNode, "y"));node.put("ass", getNodeAttrValue(childNode, "as"));node.put("relative", getNodeAttrValue(childNode, "relative"));node.put("graphId",graphId);node.put("style", getNodeAttrValue(childNode, "style"));// node.put("value", getNodeAttrValue(childNode, "value"));// node.put("source", getNodeAttrValue(childNode, "source"));// node.put("target", getNodeAttrValue(childNode, "target"));// node.put("edge", getNodeAttrValue(childNode, "edge"));// node.put("vertex", getNodeAttrValue(childNode, "vertex")); nodeMapList.add(node);// 判斷是否屬于節(jié)點(diǎn)if (childNode.getNodeType() == Node.ELEMENT_NODE) {// 判斷是否還有子節(jié)點(diǎn)parseElement((Element) childNode, "");}}}}/*** 獲取指定節(jié)點(diǎn)的指定屬性的值* @param node* @param attrName* @return*/public static String getNodeAttrValue(Node node, String attrName) {NamedNodeMap attr = node.getAttributes();if (attr != null) {Node attrNode = attr.getNamedItem(attrName);if (attrNode != null) {return attrNode.getNodeValue();}}return "";}/*** 獲取指定的document對(duì)象中要保存的節(jié)點(diǎn)對(duì)象* @param doc* @return*/public static List<Map<String, Object>> parseDocument(Document doc) {String id ="6ed10c4036f245b8bf78e1141d85e23b";// doc.getDocumentElement().getAttribute("id");if ("".equals(id)) {id = getUUID32();}// 遞歸解析ElementElement element = doc.getDocumentElement();nodeMapList.clear();parseElement(element, id);return nodeMapList;}/*** 根據(jù)圖的id獲取圖的xml字符串* @param graphId* @return*/public static String getXmlByGraphId(String graphId){xmlStr = "";// 根節(jié)點(diǎn)名稱/*String rootName = doc.getDocumentElement().getTagName();// 遞歸解析ElementElement element = doc.getDocumentElement();*/return getElementStr(null);}/*** 生成32位主鍵* @return*/public static String getUUID32() {return UUID.randomUUID().toString().replace("-", "").toLowerCase();}public static Document createDocument() {// 初始化xml解析工廠DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 創(chuàng)建DocumentBuilderDocumentBuilder builder = null;try {builder = factory.newDocumentBuilder();} catch (ParserConfigurationException e) {e.printStackTrace();}// 創(chuàng)建DocumentDocument doc = builder.newDocument();// standalone用來表示該文件是否呼叫其它外部的文件。若值是 ”yes” 表示沒有呼叫外部文件doc.setXmlStandalone(true);// 創(chuàng)建一個(gè)根節(jié)點(diǎn)// 說明:// doc.createElement("元素名")、element.setAttribute("屬性名","屬性值")、element.setTextContent("標(biāo)簽間內(nèi)容")Element diagram = doc.createElement("diagram");diagram.setAttribute("id", "");diagram.setAttribute("tcn", "");// 創(chuàng)建根節(jié)點(diǎn)第一個(gè)子節(jié)點(diǎn)Element mxGraphModel = doc.createElement("mxGraphModel");diagram.appendChild(mxGraphModel);Element root = doc.createElement("root");mxGraphModel.appendChild(root);Element mxCell1 = doc.createElement("mxCell");mxCell1.setAttribute("id", "0");root.appendChild(mxCell1);Element mxCell2 = doc.createElement("mxCell");mxCell2.setAttribute("id", "1");mxCell2.setAttribute("parent", "0");root.appendChild(mxCell2);//根據(jù)圖的id獲取圖中節(jié)點(diǎn)/*Element mxCell3 = doc.createElement("mxCell");mxCell3.setAttribute("id", "2");mxCell3.setAttribute("parent", "1");mxCell3.setAttribute("vertex", "1");mxCell3.setAttribute("value", "songyan");root.appendChild(mxCell3);Element mxGeometry = doc.createElement("mxGeometry");mxGeometry.setAttribute("x", "20");mxGeometry.setAttribute("y", "20");mxGeometry.setAttribute("width", "80");mxGeometry.setAttribute("height", "30");mxGeometry.setAttribute("as", "geometry");mxCell3.appendChild(mxGeometry);*/// 添加根節(jié)點(diǎn) doc.appendChild(diagram);return doc;}/*** 根據(jù)圖的id獲取document對(duì)象* @param graphId 圖的id* @return*/public static Document getDocumentByGraphId(String graphId) {// 初始化xml解析工廠DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 創(chuàng)建DocumentBuilderDocumentBuilder builder = null;try {builder = factory.newDocumentBuilder();} catch (ParserConfigurationException e) {e.printStackTrace();}// 創(chuàng)建DocumentDocument doc = builder.newDocument();// standalone用來表示該文件是否呼叫其它外部的文件。若值是 ”yes” 表示沒有呼叫外部文件doc.setXmlStandalone(true);// 創(chuàng)建一個(gè)根節(jié)點(diǎn)// 說明:// doc.createElement("元素名")、element.setAttribute("屬性名","屬性值")、element.setTextContent("標(biāo)簽間內(nèi)容")Element diagram = doc.createElement("diagram");diagram.setAttribute("id", "");diagram.setAttribute("tcn", "");// 創(chuàng)建根節(jié)點(diǎn)第一個(gè)子節(jié)點(diǎn)Element mxGraphModel = doc.createElement("mxGraphModel");diagram.appendChild(mxGraphModel);Element root = doc.createElement("root");mxGraphModel.appendChild(root);Element mxCell1 = doc.createElement("mxCell");mxCell1.setAttribute("id", "0");root.appendChild(mxCell1);Element mxCell2 = doc.createElement("mxCell");mxCell2.setAttribute("id", "1");mxCell2.setAttribute("parent", "0");root.appendChild(mxCell2);//根據(jù)圖的id獲取圖中節(jié)點(diǎn)//List<Map<String,Object>> transList = trans// 添加根節(jié)點(diǎn) doc.appendChild(diagram);return doc;}public static void main(String[] args) {Document document= createDocument();System.out.println(getXmlStrByDocument(document));}public static Document getDocument(List<Map<String, Object>> newNodeList,String graphId) {// 初始化xml解析工廠DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();// 創(chuàng)建DocumentBuilderDocumentBuilder builder = null;try {builder = factory.newDocumentBuilder();} catch (ParserConfigurationException e) {e.printStackTrace();}// 創(chuàng)建DocumentDocument doc = builder.newDocument();// standalone用來表示該文件是否呼叫其它外部的文件。若值是 ”yes” 表示沒有呼叫外部文件doc.setXmlStandalone(true);// 創(chuàng)建一個(gè)根節(jié)點(diǎn)// 說明:// doc.createElement("元素名")、element.setAttribute("屬性名","屬性值")、element.setTextContent("標(biāo)簽間內(nèi)容")Element diagram = doc.createElement("diagram");diagram.setAttribute("id", graphId);diagram.setAttribute("tcn", "");// 創(chuàng)建根節(jié)點(diǎn)第一個(gè)子節(jié)點(diǎn)Element mxGraphModel = doc.createElement("mxGraphModel");diagram.appendChild(mxGraphModel);Element root = doc.createElement("root");mxGraphModel.appendChild(root);Element mxCell1 = doc.createElement("mxCell");mxCell1.setAttribute("id", "0");root.appendChild(mxCell1);Element mxCell2 = doc.createElement("mxCell");mxCell2.setAttribute("id", "1");mxCell2.setAttribute("parent", "0");root.appendChild(mxCell2);for (Map<String, Object> node : newNodeList) {handleNode(root,doc,node);}// 添加根節(jié)點(diǎn) doc.appendChild(diagram);return doc;}private static void handleNode(Element root, Document doc, Map<String, Object> node) {Element mxCell = doc.createElement((String) node.get("nodeName"));Object as = node.get("as");Object width = node.get("width");Object x = node.get("x");Object y = node.get("y");Object style = node.get("style");Object nodeId = node.get("nodeId");Object height = node.get("height");Object parent = node.get("parent");Object relative = node.get("relative");Object vertex = node.get("vertex");Object value = node.get("value");Object edge = node.get("edge");Object source = node.get("source");Object target = node.get("target");if(value!=null && !"".equals(value)){mxCell.setAttribute("value", (String) value);}if(edge!=null && !"".equals(edge)){mxCell.setAttribute("edge", (String) edge);}if(source!=null && !"".equals(source)){mxCell.setAttribute("source", (String) source);}if(target!=null && !"".equals(target)){mxCell.setAttribute("target", (String) target);}if(as!=null && !"".equals(as)){mxCell.setAttribute("as", (String) as);}if(width!=null && !"".equals(width)){mxCell.setAttribute("width", (String) width);}if(x!=null && !"".equals(x)){mxCell.setAttribute("x", (String) x);}if(y!=null && !"".equals(y)){mxCell.setAttribute("y", (String) y);}if(style!=null && !"".equals(style)){mxCell.setAttribute("style", (String) style);}if(nodeId!=null && !"".equals(nodeId)){mxCell.setAttribute("id", (String) nodeId);}if(parent!=null && !"".equals(parent)){mxCell.setAttribute("parent", (String) parent);}if(height!=null && !"".equals(height)){mxCell.setAttribute("height", (String) height);}if(relative!=null && !"".equals(relative)){mxCell.setAttribute("relative", (String) relative);}if(vertex!=null && !"".equals(vertex)){mxCell.setAttribute("vertex", (String) vertex);}root.appendChild(mxCell);Object child = node.get("child");if(child!=null){List<Map<String, Object>> childNodeList = (List<Map<String, Object>>) child;for (Map<String, Object> map : childNodeList) {handleNode(mxCell, doc, map); }}}}?這個(gè)是我寫的一個(gè)工具類,包括解析xml的方法,也有些封裝成xml的方法。
下面是解析xml并將其保存到數(shù)據(jù)庫(kù)的方法
@RequestMapping(value="/save2")@ResponseBodyprotected void save2(HttpServletResponse response,HttpServletRequest request,@RequestParam String graphXml) throws Exception{String xml = StringEscapeHelper.decode(graphXml);System.out.println(xml);Document current = mxXmlUtils.parseXml(xml);String graphId = "6ed10c4036f245b8bf78e1141d85e23b";//current.getDocumentElement().getAttribute("id");System.out.println("graphId:"+graphId);transService.deleteGraphById(graphId);List<Map<String, Object>> nodeMapList = DocumentUtil.parseDocument(current);for (Map<String, Object> trans : nodeMapList) {System.out.println(trans);transService.insert(trans);}try{PrintWriter out=response.getWriter();String result="songyan";out.write(result);out.flush();out.close();}catch (Exception e){e.printStackTrace();throw new Exception(e.getMessage());}}?
?這里我是給每個(gè)圖一個(gè)唯一的id,每次保存的時(shí)候都把之前的節(jié)點(diǎn)信息刪除掉,再根據(jù)解析出來的節(jié)點(diǎn)信息,保存節(jié)點(diǎn)。
(5)節(jié)點(diǎn)信息封裝成mxgraph可以解析的xml
下面是從數(shù)據(jù)庫(kù)讀取節(jié)點(diǎn)信息,并將其轉(zhuǎn)換成xml的方法:
@ResponseBody@RequestMapping(method = RequestMethod.POST, value = "/open")protected void open(HttpServletRequest request) throws Exception {//獲取圖的idString graphId = request.getParameter("graphId");System.out.println("graphId::"+graphId);//獲取節(jié)點(diǎn)對(duì)象List<Map<String,Object>> nodeList = transService.getTransListByGraphId(graphId);List<Map<String,Object>> newNodeList = new ArrayList<Map<String,Object>>();for (Map<String, Object> node : nodeList) {Map nodeMap = node;String nodeId = (String) node.get("nodeId");//查詢子節(jié)點(diǎn)List<Map<String,Object>> childNodeList = getChildNodes(graphId,nodeId);if(childNodeList!=null && childNodeList.size()!=0){nodeMap.put("child", childNodeList);newNodeList.add(nodeMap);}}System.out.println(newNodeList);//獲取圖的document對(duì)象Document document = DocumentUtil.getDocument(newNodeList,graphId);//獲取xmlString graphXml = DocumentUtil.getXmlStrByDocument(document);System.out.println(graphXml);JsonUtils.responseXml(StringEscapeHelper.encode(graphXml));}?
(6)頁(yè)面渲染xml,回顯成圖(普通的html,js中顯示正常,集成到VUE里面之后發(fā)現(xiàn)不報(bào)錯(cuò),也不顯示,針對(duì)VUE的處理會(huì)在下面說明)
var xml = '<diagram id="" tcn=""><mxGraphModel><root><Workflow value="Diagram" id="0"><mxCell/></Workflow><Layer value="Default Layer" id="1"><mxCell parent="0"/></Layer><mxCell id="2" value="Hello, World!" parent="1" vertex="1"><mxGeometry x="120" y="90" width="80" height="40" as="geometry"/></mxCell></root></mxGraphModel></diagram>'; var doc = mxUtils.parseXml(xml); var codec = new mxCodec(doc); codec.decode(doc.documentElement.firstChild, graph.getModel());(7)Vue引入mxGraph(引入的方法很重要)
1)在項(xiàng)目的src目錄下創(chuàng)建文件夾magraph,在mxgraph文件夾創(chuàng)建index.js,Graph.js兩個(gè)文件
index.js內(nèi)容:
import mx from 'mxgraph' const mxgraph = mx({mxBasePath: '/static/mxgraph' }) // decode bug https://github.com/jgraph/mxgraph/issues/49 window.mxGraph = mxgraph.mxGraph window.mxGraphModel = mxgraph.mxGraphModel window.mxEditor = mxgraph.mxEditor window.mxGeometry = mxgraph.mxGeometry window.mxDefaultKeyHandler = mxgraph.mxDefaultKeyHandler window.mxDefaultPopupMenu = mxgraph.mxDefaultPopupMenu window.mxStylesheet = mxgraph.mxStylesheet window.mxDefaultToolbar = mxgraph.mxDefaultToolbar export default mxgraph?
Graph.js內(nèi)容:
import mxgraph from './index'; import _ from 'lodash';const {mxGraph,mxVertexHandler,mxConstants,mxCellState,mxPerimeter,mxCellEditor,mxGraphHandler,mxEvent,mxEdgeHandler,mxShape,mxConnectionConstraint,mxPoint,mxEventObject,mxCodec,mxObjectCodec,mxUtils,mxImageExport,mxXmlCanvas2D,mxCodecRegistry, } = mxgraph;Object.assign(mxEvent, {EDGE_START_MOVE: 'edgeStartMove',VERTEX_START_MOVE: 'vertexStartMove', });let pokeElementIdSeed = 0;// export class PokeElement { // constructor(element) { // this.id = pokeElementIdSeed; // pokeElementIdSeed++; // this.element = element; // this.normalType = ''; // } // } export class Graph extends mxGraph {static getStyleDict(cell) {return _.compact(cell.getStyle().split(';')).reduce((acc, item) => {const [key, value] = item.split('=');acc[key] = value;return acc;}, {});}static convertStyleToString(styleDict) {const style = Object.entries(styleDict).map(([key, value]) => `${key}=${value}`).join(';').replace(/=undefined/g, '');return `${style};`;}static getCellPosition(cell) {return _.pick(cell.getGeometry(), ['x', 'y']);}constructor(container) {super(container);this._init();}_init() {this._setDefaultConfig();this._configConstituent();this._putVertexStyle();this._setDefaultEdgeStyle();this._setAnchors();this._configCustomEvent();// this._configCoder(); }_configConstituent() {// Redirects selection to parentthis.selectCellForEvent = (...args) => {const [cell] = args;if (this.isPart(cell)) {args[0] = this.model.getParent(cell);mxGraph.prototype.selectCellForEvent.call(this, args);return;}mxGraph.prototype.selectCellForEvent.apply(this, args);};/*** Redirects start drag to parent.*/const graphHandlerGetInitialCellForEvent = mxGraphHandler.prototype.getInitialCellForEvent;mxGraphHandler.prototype.getInitialCellForEvent = function getInitialCellForEvent(...args) {// this 是 mxGraphHandlerlet cell = graphHandlerGetInitialCellForEvent.apply(this, args);if (this.graph.isPart(cell)) {cell = this.graph.getModel().getParent(cell);}return cell;};}_setDefaultConfig() {this.setConnectable(true);mxEvent.disableContextMenu(this.container);// 固定節(jié)點(diǎn)大小this.setCellsResizable(false);// 編輯時(shí)按回車鍵不換行,而是完成輸入this.setEnterStopsCellEditing(true);// 編輯時(shí)按 escape 后完成輸入mxCellEditor.prototype.escapeCancelsEditing = false;// 失焦時(shí)完成輸入mxCellEditor.prototype.blurEnabled = true;// 禁止節(jié)點(diǎn)折疊this.foldingEnabled = false;// 文本包裹效果必須開啟此配置this.setHtmlLabels(true);// 拖拽過程對(duì)齊線mxGraphHandler.prototype.guidesEnabled = true;// 禁止游離線條this.setDisconnectOnMove(false);this.setAllowDanglingEdges(false);mxGraph.prototype.isCellMovable = cell => !cell.edge;// 禁止調(diào)整線條彎曲度this.setCellsBendable(false);// 禁止從將label從線條上拖離mxGraph.prototype.edgeLabelsMovable = false;}_putVertexStyle() {const normalTypeStyle = {[mxConstants.STYLE_SHAPE]: mxConstants.SHAPE_IMAGE,[mxConstants.STYLE_PERIMETER]: mxPerimeter.RectanglePerimeter,};this.getStylesheet().putCellStyle('normalType', normalTypeStyle);const nodeStyle = {// 圖片樣式參考這個(gè)例子// https://github.com/jinzhanye/mxgraph-demos/blob/master/src/06.image.html [mxConstants.STYLE_SHAPE]: mxConstants.SHAPE_LABEL,[mxConstants.STYLE_PERIMETER]: mxPerimeter.RectanglePerimeter,[mxConstants.STYLE_ROUNDED]: true,[mxConstants.STYLE_ARCSIZE]: 6, // 設(shè)置圓角程度 [mxConstants.STYLE_STROKECOLOR]: '#333333',[mxConstants.STYLE_FONTCOLOR]: '#333333',[mxConstants.STYLE_FILLCOLOR]: '#ffffff',// [mxConstants.STYLE_LABEL_BACKGROUNDCOLOR]: 'none',[mxConstants.STYLE_ALIGN]: mxConstants.ALIGN_CENTER,[mxConstants.STYLE_VERTICAL_ALIGN]: mxConstants.ALIGN_TOP,[mxConstants.STYLE_IMAGE_ALIGN]: mxConstants.ALIGN_CENTER,[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN]: mxConstants.ALIGN_TOP,[mxConstants.STYLE_IMAGE_WIDTH]: '72',[mxConstants.STYLE_IMAGE_HEIGHT]: '72',[mxConstants.STYLE_SPACING_TOP]: '100',[mxConstants.STYLE_SPACING]: '8',};this.getStylesheet().putCellStyle('node', nodeStyle);// 設(shè)置選中狀態(tài)節(jié)點(diǎn)的邊角為圓角,默認(rèn)是直角const oldCreateSelectionShape = mxVertexHandler.prototype.createSelectionShape;mxVertexHandler.prototype.createSelectionShape = function createSelectionShape(...args) {const res = oldCreateSelectionShape.apply(this, args);res.isRounded = true;// style 屬性來自 mxShape , mxRectangle 繼承自 mxShaperes.style = {arcSize: 6,};return res;};}_setDefaultEdgeStyle() {const style = this.getStylesheet().getDefaultEdgeStyle();Object.assign(style, {[mxConstants.STYLE_ROUNDED]: true, // 設(shè)置線條拐彎處為圓角[mxConstants.STYLE_STROKEWIDTH]: '2',[mxConstants.STYLE_STROKECOLOR]: '#333333',[mxConstants.STYLE_EDGE]: mxConstants.EDGESTYLE_ORTHOGONAL,[mxConstants.STYLE_FONTCOLOR]: '#33333',[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR]: '#ffa94d',});// 設(shè)置拖拽線的過程出現(xiàn)折線,默認(rèn)為直線this.connectionHandler.createEdgeState = () => {const edge = this.createEdge();return new mxCellState(this.view, edge, this.getCellStyle(edge));};}_setAnchors() {// 禁止從節(jié)點(diǎn)中心拖拽出線條this.connectionHandler.isConnectableCell = () => false;mxEdgeHandler.prototype.isConnectableCell = () => false;// Overridden to define per-shape connection pointsmxGraph.prototype.getAllConnectionConstraints = (terminal) => {if (terminal != null && terminal.shape != null) {if (terminal.shape.stencil != null) {if (terminal.shape.stencil != null) {return terminal.shape.stencil.constraints;}} else if (terminal.shape.constraints != null) {return terminal.shape.constraints;}}return null;};// Defines the default constraints for all shapesmxShape.prototype.constraints = [new mxConnectionConstraint(new mxPoint(0, 0), true),new mxConnectionConstraint(new mxPoint(0, 1), true),new mxConnectionConstraint(new mxPoint(1, 0), true),new mxConnectionConstraint(new mxPoint(1, 1), true),new mxConnectionConstraint(new mxPoint(0.25, 0), true),new mxConnectionConstraint(new mxPoint(0.5, 0), true),new mxConnectionConstraint(new mxPoint(0.75, 0), true),new mxConnectionConstraint(new mxPoint(0, 0.25), true),new mxConnectionConstraint(new mxPoint(0, 0.5), true),new mxConnectionConstraint(new mxPoint(0, 0.75), true),new mxConnectionConstraint(new mxPoint(1, 0.25), true),new mxConnectionConstraint(new mxPoint(1, 0.5), true),new mxConnectionConstraint(new mxPoint(1, 0.75), true),new mxConnectionConstraint(new mxPoint(0.25, 1), true),new mxConnectionConstraint(new mxPoint(0.5, 1), true),new mxConnectionConstraint(new mxPoint(0.75, 1), true)];}_configCustomEvent() {const graph = this;const oldStart = mxEdgeHandler.prototype.start;mxEdgeHandler.prototype.start = function start(...args) {oldStart.apply(this, args);graph.fireEvent(new mxEventObject(mxEvent.EDGE_START_MOVE,'edge', this.state.cell,'source', this.isSource,));};const oldCreatePreviewShape = mxGraphHandler.prototype.createPreviewShape;mxGraphHandler.prototype.createPreviewShape = function createPreviewShape(...args) {graph.fireEvent(new mxEventObject(mxEvent.VERTEX_START_MOVE));return oldCreatePreviewShape.apply(this, args);};}_configCoder() {const codec = new mxObjectCodec(new PokeElement());codec.encode = function (enc, obj) {const node = enc.document.createElement('PokeElement');mxUtils.setTextContent(node, JSON.stringify(obj));return node;};codec.decode = function (dec, node, into) {const obj = JSON.parse(mxUtils.getTextContent(node));obj.constructor = PokeElement;return obj;};mxCodecRegistry.register(codec);}getDom(cell) {const state = this.view.getState(cell);return state.shape.node;}setStyle(cell, key, value) {const styleDict = Graph.getStyleDict(cell);styleDict[key] = value;const style = Graph.convertStyleToString(styleDict);this.getModel().setStyle(cell, style);}isPart(cell) {const state = this.view.getState(cell);const style = (state != null) ? state.style : this.getCellStyle(cell);return style.constituent === 1;}deleteSubtree(cell) {const cells = [];this.traverse(cell, true, (vertex) => {cells.push(vertex);return true;});this.removeCells(cells);}_restoreModel() {Object.values(this.getModel().cells).forEach(cell => {if (cell.vertex && cell.data) {cell.data = JSON.parse(cell.data);}});}// 將 data 變?yōu)樽址?#xff0c;否則還原時(shí)會(huì)報(bào)錯(cuò) _getExportModel() {const model = _.cloneDeep(this.getModel());Object.values(model.cells).forEach(cell => {if (cell.vertex && cell.data) {cell.data = JSON.stringify(cell.data);}});return model;}importModelXML(xmlTxt) {this.getModel().beginUpdate();try {const doc = mxUtils.parseXml(xmlTxt);const root = doc.documentElement;const dec = new mxCodec(root.ownerDocument);dec.decode(root, this.getModel());} finally {this.getModel().endUpdate();}this._restoreModel();}exportModelXML() {const enc = new mxCodec(mxUtils.createXmlDocument());const node = enc.encode(this._getExportModel());return mxUtils.getPrettyXml(node);}exportPicXML() {const xmlDoc = mxUtils.createXmlDocument();const root = xmlDoc.createElement('output');xmlDoc.appendChild(root);const { scale } = this.view;// 這個(gè)項(xiàng)目畫布邊寬為0,可以自行進(jìn)行調(diào)整const border = 0;const bounds = this.getGraphBounds();const xmlCanvas = new mxXmlCanvas2D(root);xmlCanvas.translate(Math.floor((border / scale - bounds.x) / scale),Math.floor((border / scale - bounds.y) / scale),);xmlCanvas.scale(1);const imgExport = new mxImageExport();imgExport.drawState(this.getView().getState(this.model.root), xmlCanvas);const w = Math.ceil(bounds.width * scale / scale + 2 * border);const h = Math.ceil(bounds.height * scale / scale + 2 * border);const xml = mxUtils.getPrettyXml(root);return {xml,w,h,};} }let graph = {};export const destroyGraph = () => {graph.destroy();graph = {}; };export const genGraph = (container) => {graph = new Graph(container);return graph; };export const getGraph = () => graph; View Code?
?
2)在使用Vue的頁(yè)面引入
import mxgraph from "../../graph/index";const {mxGraph,mxClient,mxDragSource,mxCell,mxRubberband,mxVertexHandler,mxConstants,mxCellState,mxPerimeter,mxCellEditor,mxGraphHandler,mxEvent,mxEdgeHandler,mxShape,mxConnectionConstraint,mxPoint,mxEventObject,mxCodec,mxObjectCodec,mxUtils,mxImageExport,mxXmlCanvas2D,mxClipboard,mxCodecRegistry } = mxgraph;3)cnpm安裝
xnpm install mxgraph
注:其他的方式可能也能引入但是有些功能可能不能用,比如xml渲染的時(shí)候不出錯(cuò)但是也不顯示
4)關(guān)于節(jié)點(diǎn)樣式的處理,拖拽生成圖的處理,右鍵生成菜單,右鍵刪除節(jié)點(diǎn)的功能如下
<template><el-container style="height: 500px; border: 1px solid #eee"><el-aside width="200px" style="background-color: rgb(238, 241, 246)"><el-header style="text-align: center; font-size: 16px;" class="left_header"><b>轉(zhuǎn)換管理</b></el-header><el-menu :default-openeds="['1']"><el-submenu index="1"><template slot="title"><i class="el-icon-menu"></i>輸入</template><el-menu-item-group><el-menu-item><span id="in1" class="itemstyle"></span><spanunselectable="on"qtip="從一個(gè)微軟的Excel文件里讀取數(shù)據(jù). 兼容Excel 95, 97 and 2000."id="extdd-81">Excel輸入</span></el-menu-item><el-menu-item><span id="in2" class="itemstyle"></span><spanunselectable="on"qtip="從一個(gè)文本文件(幾種格式)里讀取數(shù)據(jù){0}這些數(shù)據(jù)可以被傳遞到下一個(gè)步驟里..."id="extdd-84">文本文件輸入</span></el-menu-item><el-menu-item><span id="in3" class="itemstyle"></span><span unselectable="on" qtip="產(chǎn)生一些空記錄或相等的行." id="extdd-87">生成記錄</span></el-menu-item><el-menu-item><span id="in4" class="itemstyle"></span><span unselectable="on" qtip="Generate random value" id="extdd-90">生成隨機(jī)數(shù)</span></el-menu-item><el-menu-item><span id="in5" class="itemstyle"></span><spanunselectable="on"qtip="Enter rows of static data in a grid, usually for testing, reference or demo purpose"id="extdd-93">自定義常量數(shù)據(jù)</span></el-menu-item><el-menu-item><span id="in6" class="itemstyle"></span><span unselectable="on" qtip="獲取系統(tǒng)信息,例如時(shí)間、日期." id="extdd-96">獲取系統(tǒng)信息</span></el-menu-item><el-menu-item><span id="in7" class="itemstyle"></span><span unselectable="on" qtip="從數(shù)據(jù)庫(kù)表里讀取信息." id="extdd-99">表輸入</span></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="2"><template slot="title"><i class="el-icon-menu"></i>輸出</template><el-menu-item-group><el-menu-item><span id="out1"></span><spanunselectable="on"qtip="Stores records into an Excel (XLS) document with formatting information."id="extdd-102">Excel輸出</span></el-menu-item><el-menu-item><span id="out2"></span><spanunselectable="on"qtip="Output SQL INSERT statements to file"id="extdd-105">SQL 文件輸出</span></el-menu-item><el-menu-item><span id="out3"></span><span unselectable="on" qtip="基于關(guān)鍵字刪除記錄" id="extdd-108">刪除</span></el-menu-item><el-menu-item><span id="out4"></span><span unselectable="on" qtip="基于關(guān)鍵字更新或插入記錄到數(shù)據(jù)庫(kù)." id="extdd-90">插入 / 更新</span></el-menu-item><el-menu-item><span id="out5"></span><spanunselectable="on"qtip="This step perform insert/update/delete in one go based on the value of a field. "id="extdd-93">數(shù)據(jù)同步</span></el-menu-item><el-menu-item><span id="out6"></span><span unselectable="on" qtip="寫記錄到一個(gè)文本文件." id="extdd-96">文本文件輸出</span></el-menu-item><el-menu-item><span id="out7"></span><span unselectable="on" qtip="基于關(guān)鍵字更新記錄到數(shù)據(jù)庫(kù)" id="extdd-99">更新</span></el-menu-item><el-menu-item><span id="out8"></span><span unselectable="on" qtip="寫信息到一個(gè)數(shù)據(jù)庫(kù)表" id="extdd-102">表輸出</span></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="3"><template slot="title"><i class="el-icon-menu"></i>轉(zhuǎn)換</template><el-menu-item-group><el-menu-item><span id="trans1"></span><spanunselectable="on"qtip="Maps values of a certain field from one value to another"id="extdd-105">值映射</span></el-menu-item><el-menu-item><span id="trans2"></span><spanunselectable="on"qtip="Denormalises rows by looking up key-value pairs and by assigning them to new fields in the輸出 rows.{0}This method aggregates and needs the輸入 rows to be sorted on the grouping fields"id="extdd-108">列轉(zhuǎn)行</span></el-menu-item><el-menu-item><span id="trans3"></span><span unselectable="on" qtip="Strings cut (substring)." id="extdd-111">剪切字符串</span></el-menu-item><el-menu-item><span id="trans4"></span><spanunselectable="on"qtip="去除重復(fù)的記錄行,保持記錄唯一{0}這個(gè)僅僅基于一個(gè)已經(jīng)排好序的輸入.{1}如果輸入沒有排序, 僅僅兩個(gè)連續(xù)的記錄行被正確處理."id="extdd-114">去除重復(fù)記錄</span></el-menu-item><el-menu-item><span id="trans5"></span><span unselectable="on" qtip="給記錄增加一到多個(gè)常量" id="extdd-117">增加常量</span></el-menu-item><el-menu-item><span id="trans6"></span><span unselectable="on" qtip="從序列獲取下一個(gè)值" id="extdd-120">增加序列</span></el-menu-item><el-menu-item><span id="trans7"></span><spanunselectable="on"qtip="Add a checksum column for each input row"id="extdd-123">增加校驗(yàn)列</span></el-menu-item><el-menu-item><span id="trans8"></span><spanunselectable="on"qtip="選擇或移除記錄里的字。{0}此外,可以設(shè)置字段的元數(shù)據(jù): 類型, 長(zhǎng)度和精度."id="extdd-126">字段選擇</span></el-menu-item><el-menu-item><span id="trans9"></span><spanunselectable="on"qtip="Replace all occurences a word in a string with another word."id="extdd-129">字符串替換</span></el-menu-item><el-menu-item><span id="trans10"></span><span unselectable="on" qtip="基于字段值把記錄排序(升序或降序)" id="extdd-132">排序記錄</span></el-menu-item><el-menu-item><span id="trans11"></span><spanunselectable="on"qtip="Flattens consequetive rows based on the order in which they appear in the輸入 stream"id="extdd-135">行扁平化</span></el-menu-item><el-menu-item><span id="trans12"></span><spanunselectable="on"qtip="De-normalised information can be normalised using this step type."id="extdd-138">行轉(zhuǎn)列</span></el-menu-item></el-menu-item-group></el-submenu><el-submenu index="4"><template slot="title"><i class="el-icon-menu"></i>腳本</template><el-menu-item-group><el-menu-item><span id="scp1"></span><spanunselectable="on"qtip="This is a modified plugin for the Scripting Values with improved interface and performance. Written & donated to open source by Martin Lange, Proconis : http://www.proconis.de"id="extdd-81">JavaScript代碼</span></el-menu-item><el-menu-item><span id="scp2"></span><span unselectable="on" qtip="執(zhí)行一個(gè)SQL腳本, 另外,可以使用輸入的記錄作為參數(shù)" id="extdd-84">執(zhí)行SQL腳本</span></el-menu-item></el-menu-item-group></el-submenu></el-menu></el-aside><el-container><el-header style="text-align: left; font-size: 12px" class="right_header"><el-button type="primary" @click="clearGraph">清空</el-button><el-button type="primary" @click="lookXML">查看xml</el-button><el-button type="primary" @click="save">保存</el-button></el-header><el-main><div ref="graph_container" id="right"></div></el-main></el-container></el-container><!-- <div ref="graph_container"></div> --> </template><script> import mxgraph from "../../graph/index";const {mxGraph,mxClient,mxDragSource,mxCell,mxRubberband,mxVertexHandler,mxConstants,mxCellState,mxPerimeter,mxCellEditor,mxGraphHandler,mxEvent,mxEdgeHandler,mxShape,mxConnectionConstraint,mxPoint,mxEventObject,mxCodec,mxObjectCodec,mxUtils,mxImageExport,mxXmlCanvas2D,mxClipboard,mxCodecRegistry } = mxgraph;import api from "@/utils/api"; export default {data() {return {graph: null,undoMng: null};},name: "HelloWorld",props: {// msg: String },created() {},methods: {save() {var xml ='<diagram id="" tcn="">' +mxUtils.getXml(new mxCodec().encode(this.graph.getModel())) +"</diagram>";api("appserver/getAppServer", "post", { gid: "01" }).then(response => {console.log("response");consoele.log(response);/* this.temp.name = response.namethis.temp.details = response.detailsthis.temp.iconurl = response.iconurlthis.temp.operateType = 'U'this.temp.flowtype = response.flowtypethis.imageUrl = response.iconshowurl */// this.isLoading = false }).catch(() => {//this.isLoading = false });},clearGraph(graph) {alert("clear");this.undoMng.undo();this.undoMng.redo();},createDragSource(graph) {//創(chuàng)建輸入拖動(dòng)源var in1 = this.createDragImage(graph,"in1","./images/XLI.png","EXCEL輸入");var in2 = this.createDragImage(graph,"in2","./images/TFI.png","文本文件輸入");var in3 = this.createDragImage(graph,"in3","./images/GEN.png","生成記錄");var in4 = this.createDragImage(graph,"in4","./images/RVA.png","生成隨機(jī)數(shù)");var in5 = this.createDragImage(graph,"in5","./images/GNR.png","自定義常量數(shù)據(jù)");var in6 = this.createDragImage(graph,"in6","./images/SYS.png","獲取系統(tǒng)信息");var in7 = this.createDragImage(graph,"in7","./images/TIP.png","表輸入");//創(chuàng)建輸出拖動(dòng)源var out1 = this.createDragImage(graph,"out1","./images/XLO.png","Excel輸出");var out2 = this.createDragImage(graph,"out2","./images/SFO.png","SQL 文件輸出");var out3 = this.createDragImage(graph,"out3","./images/Delete.png","刪除");var out4 = this.createDragImage(graph,"out4","./images/INU.png","插入 / 更新");var out5 = this.createDragImage(graph,"out5","./images/SAM.png","數(shù)據(jù)同步");var out6 = this.createDragImage(graph,"out6","./images/TFO.png","文本文件輸出");var out7 = this.createDragImage(graph,"out7","./images/UPD.png","更新");var out8 = this.createDragImage(graph,"out8","./images/TOP.png","表輸出");//創(chuàng)建轉(zhuǎn)換拖動(dòng)源var trans1 = this.createDragImage(graph,"trans1","./images/VMAP.png","值映射");var trans2 = this.createDragImage(graph,"trans2","./images/UNP.png","列轉(zhuǎn)行");var trans3 = this.createDragImage(graph,"trans3","./images/SRC.png","剪切字符串");var trans4 = this.createDragImage(graph,"trans4","./images/UNQ.png","去除重復(fù)記錄");var trans5 = this.createDragImage(graph,"trans5","./images/CST.png","增加常量");var trans6 = this.createDragImage(graph,"trans6","./images/SEQ.png","增加序列");var trans7 = this.createDragImage(graph,"trans7","./images/CSM.png","增加校驗(yàn)列");var trans8 = this.createDragImage(graph,"trans8","./images/SEL.png","字段選擇");var trans9 = this.createDragImage(graph,"trans9","./images/RST.png","字符串替換");var trans10 = this.createDragImage(graph,"trans10","./images/SRT.png","排序記錄");var trans11 = this.createDragImage(graph,"trans11","./images/FLA.png","行扁平化");var trans12 = this.createDragImage(graph,"trans12","./images/NRM.png","行轉(zhuǎn)列");//創(chuàng)建腳本拖動(dòng)源var scp1 = this.createDragImage(graph,"scp1","./images/SCR_mod.png","scp1");var scp2 = this.createDragImage(graph,"scp2","./images/SQL.png","scp2");},paseXML(graph) {var xml ='<mxGraphModel> <root> <mxCell id="0"/> <mxCell id="1" parent="0"/> <mxCell id="2" value="EXCEL輸入" style="in1" vertex="1" parent="1"> <mxGeometry x="100" y="110" width="50" height="50" as="geometry"/> </mxCell> <mxCell id="3" value="文本文件輸入" style="in2" vertex="1" parent="1"> <mxGeometry x="380" y="130" width="50" height="50" as="geometry"/> </mxCell> <mxCell id="4" value="生成隨機(jī)數(shù)" style="in4" vertex="1" parent="1"> <mxGeometry x="210" y="350" width="50" height="50" as="geometry"/> </mxCell> <mxCell id="6" edge="1" parent="1" source="2" target="4"> <mxGeometry relative="1" as="geometry"/> </mxCell> <mxCell id="7" edge="1" parent="1" source="4" target="3"> <mxGeometry relative="1" as="geometry"/> </mxCell> </root> </mxGraphModel>';var doc = mxUtils.parseXml(xml);var codec = new mxCodec(doc);codec.decode(doc.documentElement, graph.getModel());},RightMenu(graph) {var container = document.getElementById("right");//禁用瀏覽器自帶的右鍵事件 mxEvent.disableContextMenu(container);// 使用本地函數(shù)安裝彈出菜單處理程序graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {return createPopupMenu(graph, menu, cell, evt);};//創(chuàng)建右鍵的菜單function createPopupMenu(graph, menu, cell, evt) {if (cell != null) {menu.addItem("復(fù)制步驟", "", function() {var cells = new Array();cells = graph.getSelectionCells();console.log("graph");console.log(graph);console.log("cells");console.log(cells);console.log("mxClipboard", mxClipboard);mxClipboard.copy(graph, cells);});}menu.addSeparator();menu.addItem("刪除步驟", "", function() {var cells = new Array();cells = graph.getSelectionCells();graph.removeCells(cells);});}},lookXML() {var encoder = new mxCodec();var node = encoder.encode(this.graph.getModel());const h = this.$createElement;this.$msgbox({title: "xml",message: h("p", null, [h("div",{style:"overflow-y:auto; overflow-x:auto; width:400px; max-height:400px;"},mxUtils.getPrettyXml(node))]),showCancelButton: true,confirmButtonText: "確定",cancelButtonText: "取消"});},getStyle(graph, url, styleName) {// 聲明一個(gè)objectvar style = {};// 克隆一個(gè)objectstyle = mxUtils.clone(style);style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL; // 不設(shè)置這個(gè)屬性 背景圖片不出來// 邊框顏色style[mxConstants.STYLE_STROKECOLOR] = "#15428b";//圓角style[mxConstants.STYLE_ROUNDED] = "1";// 邊框大小style[mxConstants.STYLE_STROKEWIDTH] = "0.5px";// 字體顏色style[mxConstants.STYLE_FONTCOLOR] = "#000";// 文字水平方式style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_right;// 文字垂直對(duì)齊style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;// 字體大小style[mxConstants.STYLE_FONTSIZE] = 14;style[mxConstants.STYLE_FILLCOLOR] = "transparent";// 底圖水平對(duì)齊style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_LEFT;// 底圖垂直對(duì)齊style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;// 圖片路徑//style[mxConstants.STYLE_IMAGE] = 'images/icons48/gear.png';style[mxConstants.STYLE_IMAGE] = url; //'./images/i_assignedSlave.png';// 背景圖片寬style[mxConstants.STYLE_IMAGE_WIDTH] = 40;// 背景圖片高style[mxConstants.STYLE_IMAGE_HEIGHT] = 40;// 上間距設(shè)置// 即使下邊定義了全局設(shè)置,但這里單獨(dú)設(shè)置上邊間距仍單獨(dú)有效// style[mxConstants.STYLE_SPACING_TOP] = 'spacingTop';// 四邊間距設(shè)置style[mxConstants.STYLE_SPACING] = 1;style[mxConstants.STYLE_VERTICAL_LABEL_POSITION] =mxConstants.ALIGN_BOTTOM;graph.getStylesheet().putCellStyle(styleName, style);},createDragImage(graph, id, image, text) {var img = mxUtils.createImage(image);img.style.width = "30px";img.style.height = "30px";img.style.margin = "0px";document.getElementById(id).appendChild(img);var style = this.getStyle(graph, image, id);// 檢查圖形中是否包含對(duì)應(yīng)的elt節(jié)點(diǎn)function containsElt(graph, elt) {while (elt != null) {if (elt == graph.container) {return true;}elt = elt.parentNode;}return false;}// 在給定的位置插入一個(gè)元素var funct1 = function(graph, evt, target, x, y) {/* var prefix = '';prefix = prefix+'verticalLabelPosition=bottom;verticalAlign=top;STYLE_STROKEWIDTH=1px;'; */var cell = new mxCell(text, new mxGeometry(0, 0, 50, 50), id);cell.vertex = true;var cells = graph.importCells([cell], x, y, target); //插入元素、位置、大小 console.log(cells.getStyle);};// 禁用IE瀏覽器中的DnD功能(這是為了跨瀏覽器平臺(tái)而設(shè)計(jì)的,見下文)if (mxClient.IS_IE) {mxEvent.addListener(img, "dragstart", function(evt) {evt.returnValue = false;});}// 創(chuàng)建拖動(dòng)源的預(yù)覽var dragElt = document.createElement("div");dragElt.style.border = "dashed black 1px";dragElt.style.width = "120px";dragElt.style.height = "40px";// 在點(diǎn)擊拖動(dòng)源圖標(biāo)時(shí)提供預(yù)覽。 預(yù)覽是提供的僅僅是拖動(dòng)源的圖片// 只有拖動(dòng)源到容器內(nèi)時(shí)才會(huì)顯示元素的坐標(biāo)預(yù)覽var ds = mxUtils.makeDraggable(img,graph,funct1,dragElt,null,null,graph.autoscroll,true);//從拖動(dòng)源拖動(dòng)時(shí)顯示導(dǎo)航線。//注意,對(duì)圖形中已存在的元素拖動(dòng)時(shí)顯示導(dǎo)航線不在本方法約束范圍。ds.isGuidesEnabled = function() {return graph.graphHandler.guidesEnabled;};//從拖動(dòng)源拖動(dòng)元素到圖形以外的區(qū)域時(shí),顯示拖動(dòng)源圖片預(yù)覽ds.createDragElement = mxDragSource.prototype.createDragElement;}},// /item1 mounted() {var graph = new mxGraph(this.$refs.graph_container);graph.setConnectable(true);new mxRubberband(graph);var parent = graph.getDefaultParent();this.graph = graph;//創(chuàng)建拖拽源this.createDragSource(graph);//頁(yè)面初始化this.paseXML(graph);//右鍵菜單定義this.RightMenu(graph);} }; </script><style scoped> .left_header {font-weight: 500;margin: 0 auto;padding: 15px; } .right_header {margin: auto 0;background-color: #e9edf1;padding: 10px;padding-left: 15px; } #right {height: 100%;position: relative;overflow: hidden;width: 100%;height: 100%;background: url("/images/grid.gif");cursor: default; }.el-menu-item-group__title {padding: 0px 0 7px 20px;line-height: normal;font-size: 12px;color: #909399; } </style> View Code?
效果圖
?
轉(zhuǎn)載于:https://www.cnblogs.com/excellencesy/p/11385806.html
總結(jié)
以上是生活随笔為你收集整理的mxgraph初体验的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IntelliJ IDEA - 自定义
- 下一篇: 两条边延长角会有什么变化_《直线、射线、