Write custom directory title here
- foreword
- environment
- npm introduces mxgraph
- Build a flowchart
- Flowchart initialization
- page effect
Foreword
When using mxGraph to echo the flow chart, there is a problem that the label is too long and overlapped. It is necessary to add a tooltip to display the complete code when the mouse hovers over it.
Environment
vue:^3.2.36
mxgraph:^4.2.2
npm introduces mxgraph
// package.json "dependencies": {<!-- --> "mxgraph": "^4.2.2", // .... other dependencies }
Construction flowchart
const loadDate = (data, graph) => {<!-- --> const parent = graph. getDefaultParent(); const obVer = new Map(); graph.getStylesheet().putCellStyle('e1', {<!-- --> strokeColor: 'green', strokeWidth: 2 }); graph.getStylesheet().putCellStyle('e2', {<!-- --> strokeColor: '#ccc', strokeWidth: 2 }); // Open the tooltip property graph.setTooltips(true); // set the mouseover style graph.getCursorForCell = function (cell) {<!-- --> if (cell !== null & amp; & amp; cell.value !== null & amp; & amp; cell.vertex === true) {<!-- --> return 'pointer'; } }; graph.setConnectable(false); // disable drag and drop connection graph.getSelectionModel().cellsSelectable = false; // disable selection graph.getModel().beginUpdate(); try {<!-- --> data.forEach((item, index) => {<!-- --> item.forEach((itemSub, indexSub) => {<!-- --> const style1: any = {<!-- -->}; style1[mx.mxConstants.STYLE_SHAPE] = mx.mxConstants.SHAPE_IMAGE; style1[mx.mxConstants.STYLE_IMAGE] = itemSub.icon; style1[mx.mxConstants.STYLE_FONTCOLOR] = '#666'; style1.verticalLabelPosition = 'bottom'; graph.getStylesheet().putCellStyle('setp' + index + '-' + indexSub, style1); const indexItem = graph.insertVertex( parent, null, itemSub.label, 20 + index * 250, parseInt(totalHeight.value) / 2 + 80 * indexSub - item.length * 40, 80, 40, 'setp' + index + '-' + indexSub ); // Override the getLabel function graph.getLabel = function (cell) {<!-- --> if (this. getModel(). isVertex(cell)) {<!-- --> const label = mx.mxGraph.prototype.getLabel.apply(this, arguments); return this. ellipseText(label, cell); } return mx.mxGraph.prototype.getLabel.apply(this, arguments); }; // Override the ellipseText function graph.ellipseText = function (label, cell) {<!-- --> const vertexWidth = this.view.getState(cell).width; const div = document. createElement('div'); div.style.position = 'absolute'; div.style.height = '20px'; div.style.overflow = 'hidden'; div.style.whiteSpace = 'nowrap'; div. innerHTML = label; document.body.appendChild(div); let textWidth = div. offsetWidth; document.body.removeChild(div); // The length of the label is less than or equal to the width of the element, so there is no need to omit it if (textWidth <= vertexWidth) {<!-- --> return label; } const dots = '...'; // The maximum number of characters that an element can display (can also be dynamically set by custom rules) let maxChars = Math. floor((label. length * vertexWidth) / textWidth); // You can adjust the pixels of the ellipsis position const minDiff = 5; while (textWidth > vertexWidth - 2 * (dots. length + minDiff) & amp; & amp; maxChars > 1) {<!-- --> maxChars -= 1; div.textContent = label.substring(0, maxChars); textWidth = div. offsetWidth; } const result = label. substring(0, maxChars) + dots; return result; }; obVer.set(index + '-' + indexSub, {<!-- --> graphItem: indexItem, itemData: itemSub }); // arrow if (index > 0 & amp; & amp; index < data.length) {<!-- --> obVer.forEach((obVeritem, key) => {<!-- --> // traverse the previous if (key. indexOf(index - 1 + '-') > -1) {<!-- --> // debugger; const getGlItem = obVer. get(key); const e1 = graph. insertEdge( parent, null, '', getGlItem.graphItem, indexItem, itemSub.isGrayArrow ? 'e2' : 'e1' ); } }); } }); }); } finally {<!-- --> graph.getModel().endUpdate(); } };
Flowchart initialization
const init = async (container: HTMLDivElement) => {<!-- --> const graph = new mx.mxGraph(container); const style = graph. getStylesheet(). getDefaultEdgeStyle(); stye[mx.mxConstants.STYLE_EDGE] = mx.mxEdgeStyle.ElbowConnector; style[mx.mxConstants.STYLE_ROUNDED] = true; graph.alternateEdgeStyle = 'elbow=vertical'; // can edit graph. setEnabled(false); // Whether it can be moved as a whole graph.panningHandler.useLeftButtonForPanning = true; loadDate(props. JSDate, graph); // Get the tooltip component var tooltip = new mx.mxTooltipHandler(graph); tooltip.init(); const tool:any = document.getElementsByClassName('mxTooltip')[0]; tool.style.cssText = "position:absolute;width:240px;boxShadow: 3px 3px 12px #C0C0C0;background: #FFFFCC;border-style: solid;border-width: 1px;border-color: black;font-family: Arial;font-size: 8pt;cursor: default;padding: 4px;color: black;" // Define the mouse hover to display the full text graph.getTooltipForCell = function (cell) {<!-- --> if (this. getModel(). isVertex(cell)) {<!-- --> return cell. value; } }; };
Page effect
At present, this implementation method is problematic
The first div whose className is mxTooltip is generated by tooltip.init(); code; the second div is generated when the mouse hovers. The prompt text seen on the page is the first div, and the second div is not displayed on the page (positioning problem).
In order to avoid more dom nodes whose className is mxTooltip on the page, the dom must be cleared every time the pop-up window is closed.
// Get all elements whose class is mxTooltip const elements:any = document.getElementsByClassName('mxTooltip'); // Traverse the list of obtained elements and remove each element in turn while (elements. length > 0) {<!-- --> elements[0].parentNode.removeChild(elements[0]); }