js插件 | 插件特色 | 文档 |
---|---|---|
antv-x6 | 优先举荐应用,开源代码收费,文档为中文 | 中文文档 demo |
gojs | 有代码,能够集体应用,商业应用须要受权,兼容性比拟好 | 英文文档https://gojs.net.cn/samples/m... |
mxGraph | 开源收费代码,然而算法不怎么敌对,简单的流程不举荐应用 | 英文文档http://jgraph.github.io/mxgraph/docs/manual.html |
antv-x6
1、援用js插件
<script src="./source/js/antv_x6/x6.js"></script><script src="./source/js/antv_x6/layout.min.js"></script>
2、创立div及节点款式
<div id="container"></div><style>.antv_x6_node_Orange { width: 100%; height: 100%; display: flex; border: 1px solid #b5b1b1; place-content: center; align-items: center; /* background: #61D2F7; */ background: -webkit-linear-gradient(top,#61D2F7,#f8f8f8); flex-direction: column; border-radius: 4px; color: rgb(34, 34, 34); cursor: pointer; box-shadow: rgb(0 112 204 / 6%) 0px 2px 3px 0px;}.antv_x6_node_Orange > img { margin-bottom: 10px;}.antv_x6_node_Orange > span { font-size: 12px; text-align: center; width: 100%; overflow: hidden; text-overflow: ellipsis; word-break: break-all; -webkit-line-clamp: 1; -webkit-box-orient: vertical; display: -webkit-box;}</style>
3、数据格式
let data = { "nodes": [{ "id": "100014", "type": "1", "value": "1111" }, { "id": "100015", "type": "1", "value": "2" }, { "id": "100016", "type": "1", "value": "3" }, { "id": "100017", "type": "1", "value": "4" }, { "id": "100018", "type": "1", "value": "5" }, { "id": "100019", "type": "1", "value": "6" }, { "id": "100020", "type": "1", "value": "7" }, { "id": "100021", "type": "1", "value": "8" }, { "id": "100022", "type": "1", "value": "9" }, { "id": "100023", "type": "1", "value": "10" }, { "id": "100024", "type": "1", "value": "11" }, { "id": "100025", "type": "1", "value": "12" }, { "id": "100026", "type": "1", "value": "13" }, { "id": "100027", "type": "1", "value": "14" }, { "id": "100028", "type": "1", "value": "15" }, { "id": "100029", "type": "1", "value": "16" }, { "id": "100030", "type": "1", "value": "17" }, { "id": "100031", "type": "1", "value": "18" }, { "id": "100032", "type": "1", "value": "19" }, { "id": "100033", "type": "1", "value": "20" }, { "id": "100034", "type": "1", "value": "21" }, { "id": "100035", "type": "1", "value": "22" }, { "id": "100036", "type": "1", "value": "23" }, { "id": "100037", "type": "1", "value": "24" } ], "edges": [ { "source": "100014", "target": "100015" }, { "source": "100015", "target": "100016" }, { "source": "100016", "target": "100017" }, { "source": "100017", "target": "100018" }, { "source": "100018", "target": "100019" }, { "source": "100017", "target": "100020" }, { "source": "100017", "target": "100021" }, { "source": "100017", "target": "100022" }, { "source": "100017", "target": "100023" }, { "source": "100017", "target": "100024" }, { "source": "100024", "target": "100025" }, { "source": "100024", "target": "100026" }, { "source": "100024", "target": "100027" }, { "source": "100024", "target": "100028" }, { "source": "100024", "target": "100029" }, { "source": "100025", "target": "100030" }, { "source": "100026", "target": "100030" }, { "source": "100027", "target": "100030" }, { "source": "100028", "target": "100030" }, { "source": "100029", "target": "100030" }, { "source": "100019", "target": "100031" }, { "source": "100020", "target": "100031" }, { "source": "100021", "target": "100031" }, { "source": "100022", "target": "100031" }, { "source": "100023", "target": "100031" }, { "source": "100030", "target": "100031" }, { "source": "100031", "target": "100032" }, { "source": "100032", "target": "100033" }, { "source": "100033", "target": "100034" }, { "source": "100034", "target": "100035" }, { "source": "100035", "target": "100036" }, { "source": "100036", "target": "100037" } ] }
4、js办法
//初始化画布function initGraph (mapContainer, mapWidth, mapHeight) { const graph = new X6.Graph(getGraphData(mapContainer, mapWidth, mapHeight)); return graph}//初始化获取画布配置,参数(地图容器,宽度,高度)function getGraphData(mapContainer, mapWidth, mapHeight) {//浏览器宽度const windowWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;//浏览器高度var windowHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight || 500; windowHeight = windowHeight < 500 ? 500 :windowHeight // 画布容器对象 const container = document.getElementById(mapContainer); console.log(mapContainer, mapWidth, mapHeight); const graphData = { container: container, width: mapWidth || windowWidth, //画布宽度 height: mapHeight || windowHeight - 20, //画布高度 background: { color: "#fffbe6", // 设置画布背景色彩 }, grid: { size: 10, // 网格大小 10px visible: true, // 渲染网格背景 }, scroller: { enabled: true,//画布是否有滚动条 pannable: true, className: "my-scroller", }, mousewheel: { enabled: true, modifiers: ["ctrl", "meta"], }, connecting: { router: { name: "manhattan",//连接线为直线 // name: "metro",//弯线 }, }, }; return graphData;}// 布局对象const { DagreLayout } = window.layout;// 算法布局const dagreLayout = new DagreLayout({ type: "dagre", rankdir: "LR",//布局的方向 align: "DL",//节点对齐形式 ranksep: 20,//层间距 nodesep: 10,//节点间隔 controlPoints: true,});// 连线款式const edgeType = {};function formatEdge(edgesData) { for (var i in edgesData) { var edge = edgesData[i]; let attrs = { line: { stroke: "#b5b1b1",//连线的色彩 strokeWidth: 1.5,//连线宽度 }, }; edge.attrs = attrs; Object.assign(edge, edgeType); } console.log(edgesData); return edgesData;}function layoutGraph (data) { var newModel = dagreLayout.layout(data) return newModel}//创立节点function createNodeDom (doc, value, type) { // doc对象间接援用页面传至,缩小反复获取doc对象 var wrap = null if (!doc) doc = document // 创立div wrap = doc.createElement('DIV') wrap.className = 'antv_x6_node_Orange' // 创立span 展现数据 span = doc.createElement('SPAN') span.innerText = value span.title = value // 将span 与 img 增加到wrap中 wrap.appendChild(span) return wrap}//数据格式化function x6DataFormat (data, doc) { var nodes = data.nodes var edges = data.edges var x6Nodes = [] var x6Data = {} for (var i in nodes) { var nodeData = nodes[i] var value = nodeData.value var type = nodeData.type var nodeHtmlData = {} if (!doc) doc = document var wrapDom = createNodeDom(doc, value, type) nodeHtmlData.id = nodeData.id nodeHtmlData.shape = 'html' nodeHtmlData.width = 64 nodeHtmlData.height = 30, nodeHtmlData.html = wrapDom x6Nodes.push(nodeHtmlData) } var newedges = formatEdge(edges)//连线 x6Data.nodes = x6Nodes x6Data.edges = newedges return x6Data}
5、js调用
// 初始化画布const graph = initGraph("container");// 获取后盾数据并格式化var x6Data = x6DataFormat(data, document);const newModel = layoutGraph(x6Data);// const newModel = x6Data;graph.fromJSON(newModel);// 将画布内容核心与视口核心对齐graph.centerContent();//节点点击事件graph.on("node:click", function ( event ) { console.log(event)});
6、效果图
mxGraph
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script type="text/javascript"> mxBasePath = '../src'; </script> <style> #graphContainer { position: absolute; top: 0; left: 0; right: 0; bottom: 0; overflow: auto; } </style> <!--引入反对库文件 --> <script type="text/javascript" src="../src/js/mxClient.js"></script></head><body> <div id="graphContainer"></div></body><script> if (!mxClient.isBrowserSupported()) { // 判断是否反对mxgraph mxUtils.error("Browser is not supported!", 200, false); } else { // 在容器中创立图表 let container = document.getElementById("graphContainer"); var model = new mxGraphModel(); var graph = new mxGraph(container, model); //设置元素可被连接线连贯 graph.setConnectable(false); //设置元素可编辑,不然无奈主动布局 graph.setCellsLocked(false); //设置两个节点是否能够建设多个连贯 graph.setMultigraph(false); //cell创立反对传入html graph.setHtmlLabels(true); //是否容许线独自存在 graph.setAllowDanglingEdges(false); //设置cell可选中 graph.setCellsSelectable(false); //设置面板能够扩充 graph.setPanning(false); graph.setDisconnectOnMove(false) //边被拖时,始终保持连贯 mxGraphHandler.prototype.guidesEnabled = false // 启用对齐线帮忙定位 // // 设置主动调整大小 // graph.setAutoSizeCells(true); // graph.setPanning(true); // graph.panningHandler.useLeftButtonForPanning = true; // // 容许连线的指标和源是同一元素 // graph.setAllowLoops(true); //自定义连线 mxEdgeStyle.MyStyle = function (state, source, target, points, result) { if (source != null && target != null) { console.log(state, source, target, points, result) // var pt = new mxPoint(target.getCenterX(), source.getCenterY()); var pt = new mxPoint(target.x, 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 style = graph.getStylesheet().getDefaultVertexStyle(); style[mxConstants.STYLE_FILLCOLOR] = "#61D2F7";//节点背景色彩 style[mxConstants.STYLE_STROKECOLOR] = "#797979";//节点边框色彩 style[mxConstants.STYLE_GRADIENTCOLOR] = '#ffffff';//节点背景渐变色 style[mxConstants.STYLE_STROKEWIDTH] = 1.5;//节点边框宽度 style[mxConstants.STYLE_FONTCOLOR] = "#000";//节点字体色彩 style[mxConstants.STYLE_FONTSIZE] = 15;//节点字体大小 style[mxConstants.STYLE_SPACING] = 10;//节点自适应内边距 // style[mxConstants.STYLE_SPACING_BOTTOM] = 30; style = graph.getStylesheet().getDefaultEdgeStyle(); style[mxConstants.STYLE_ROUNDED] = true;//边线是否圆角 style[mxConstants.STYLE_STROKECOLOR] = "#797979";//边线色彩 // style[mxConstants.STYLE_ORTHOGONAL] = "orthogonal"; style[mxConstants.STYLE_STROKEWIDTH] = 1.5;//边线宽度 style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector // style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ToptBottom // style[mxConstants.STYLE_EDGE] = mxEdgeStyle.LeftToRight; // style[mxConstants.STYLE_EDGE] = mxEdgeStyle.OrthConnector; // style[mxConstants.STYLE_EDGE] = mxEdgeStyle.SegmentConnector; // style[mxConstants.STYLE_EDGE] = mxEdgeStyle.MyStyle; // style[mxConstants.STYLE_EDGE]= mxEdgeStyle.EntityRelation style[mxConstants.STYLE_ORTHOGONAL_LOOP] = 1; style[mxConstants.STYLE_JETTY_SIZE] = "auto"; var parent = graph.getDefaultParent(); graph.getModel().beginUpdate(); try { //数据格式转化 var result = { "nodes": [ { "id": "10001", "value": "1", "type": "2" }, { "id": "2", "value": "2", "type": "1" }, { "id": "3", "value": "3", "type": "1" }, { "id": "4", "value": "4" }, { "id": "5", "value": "5", "type": "1" }, { "id": "6", "value": "6" }, { "id": "7", "value": "7" }, { "id": "8", "value": "8" }, { "id": "9", "value": "9" }, { "id": "10", "value": "10" }, { "id": "11", "value": "11" }, { "id": "12", "value": "12" }, { "id": "13", "value": "13" }, { "id": "14", "value": "14" }, { "id": "15", "value": "15" }, { "id": "16", "value": "16" }, { "id": "17", "value": "17" }, { "id": "18", "value": "18测试" }, { "id": "19", "value": "18测试" }, { "id": "20", "value": "18测试" } ], "edges": [ { "source": "10001", "target": "2" }, { "source": "2", "target": "3" }, { "source": "3", "target": "4" }, { "source": "4", "target": "5" }, { "source": "5", "target": "6" }, { "source": "4", "target": "7" }, { "source": "4", "target": "8" }, { "source": "4", "target": "9" }, { "source": "4", "target": "10" }, { "source": "4", "target": "11" }, { "source": "11", "target": "13" }, { "source": "11", "target": "12" }, { "source": "11", "target": "14" }, { "source": "11", "target": "15" }, { "source": "11", "target": "16" }, { "source": "12", "target": "17" }, { "source": "13", "target": "17" }, { "source": "14", "target": "17" }, { "source": "15", "target": "17" }, { "source": "16", "target": "17" }, { "source": "6", "target": "18" }, { "source": "7", "target": "18" }, { "source": "8", "target": "18" }, { "source": "9", "target": "18" }, { "source": "10", "target": "18" }, { "source": "17", "target": "18" }, { "source": "5", "target": "19" } ] } var childList = [] for (let i = 0; i < result.nodes.length; i++) { var childId = result.nodes[i].id; child = graph.insertVertex( parent, result.nodes[i].id,//节点id,id不能为1 result.nodes[i].value,//节点内容 0,//程度居中 30,//间隔顶部高度 130,//节点宽度 30,//节点高度 ) childList.push(child) } // console.log(childList) for (let i = 0; i < result.edges.length; i++) { var source = getNodeData(childList, result.edges[i].source); var target = getNodeData(childList, result.edges[i].target); graph.insertEdge(parent, null, '', source, target); } } finally { // Updates the display graph.getModel().endUpdate(); } // 主动布局 // let layout = new mxFastOrganicLayout(graph);//组织构造,排除 // let layout = new mxCompactTreeLayout(graph);//树型构造 // mxCompactTreeLayout.prototype.resetEdges = false // mxCompactTreeLayout.prototype.levelDistance = 10 // mxCompactTreeLayout.prototype.horizontal = false // mxCompactTreeLayout.prototype.invert = true // mxCompactTreeLayout.prototype.resizeParent = false // mxCompactTreeLayout.prototype.maintainParentLocation = true // mxCompactTreeLayout.prototype.groupPaddingTop = 10 // mxCompactTreeLayout.prototype.groupPaddingRight = 100 // mxCompactTreeLayout.prototype.nodeDistance = 20 var layout = new mxHierarchicalLayout(graph, mxConstants.DIRECTION_WEST, true); mxHierarchicalLayout.prototype.intraCellSpacing = 30 mxHierarchicalLayout.prototype.fineTuning = false mxHierarchicalLayout.prototype.traverseAncestors = false mxHierarchicalLayout.prototype.resizeParent = true // 无关系实体之间的间距 mxHierarchicalLayout.prototype.interHierarchySpacing = 20 // 层级之间的间隔 mxHierarchicalLayout.prototype.interRankCellSpacing = 50 // mxHierarchicalLayout.prototype.crossingStage = true mxHierarchicalLayout.prototype.parallelEdgeSpacing = 0 // layout.orientation=mxConstants.DIRECTION_NORTH; // var layout = new mxSwimlaneLayout(graph); // var layout = new mxCircleLayout(graph);//圆形构造,排除 // var layout = new mxEdgeLabelLayout(graph);//排除 // var layout = new mxParallelEdgeLayout(graph);//排除 // var layout = new mxPartitionLayout(graph, true, 10, 20);//排除 // var layout = new mxRadialTreeLayout(graph, false, 30, 200);//排除 // var layout = new mxStackLayout(graph, true, 100, 200);//排除 layout.disableEdgeStyle = false; // console.log(layout) layout.execute(graph.getDefaultParent()); // 居中 var bounds = graph.getGraphBounds(); var margin = margin || 10; graph.container.style.overflow = "hidden"; graph.view.setTranslate( -bounds.x - (bounds.width - graph.container.clientWidth) / 2, -bounds.y - (bounds.height - graph.container.clientHeight) / 2 ); while ((bounds.width + margin * 2) > graph.container.clientWidth || (bounds.height + margin * 2) > graph.container.clientHeight) { graph.zoomOut(); bounds = graph.getGraphBounds(); } graph.container.style.overflow = "auto"; } // 获取节点格局 function getNodeData(childList, value) { let getNode; for (let j = 0; j < childList.length; j++) { if (childList[j].id == value) { getNode = childList[j] } } // console.log(value, getNode) return getNode }</script></html>