共计 12757 个字符,预计需要花费 32 分钟才能阅读完成。
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>
正文完