上示例图
一、鼠标覆盖部分节点tooltip不显示问题处理
现象
以下注释掉的这段代码是为节点添加tooltip的方式之一,但会有tooltip隐藏后覆盖节点导致鼠标移动到节点上不出现新的tooltip的现象
modes: {
default: [
"drag-node",
"zoom-canvas",
"drag-canvas",
// {
// type: 'tooltip',
// formatText: function formatText(model) {
// // var text = 'description: ' + model.description;
// let str = '';
// nodeInfo.forEach((it) => {
// if (it.id === model.id) {
// str = it.description;
// }
// });
// var text = str;
// return text;
// },
// shouldUpdate: function shouldUpdate(e) {
// return true;
// },
// },
{
type: "edge-tooltip",
formatText: function formatText(model) {
let str = "";
edgesInfo.forEach((it) => {
let mId = model.start + ":" + model.end;
if (it.id === mId) {
str = it.description;
}
});
var text = str;
return text;
},
shouldUpdate: function shouldUpdate(e) {
return true;
},
},
],
},
解决方式
const tooltip = new G6.Tooltip({
// offsetX and offsetY include the padding of the parent container
offsetX: 20,
offsetY: 30,
// the types of items that allow the tooltip show up
// 允许出现 tooltip 的 item 类型
itemTypes: ["node"],
// custom the tooltip's content
// 自定义 tooltip 内容
getContent: (e) => {
const outDiv = document.createElement("div");
//outDiv.style.padding = '0px 0px 20px 0px';
const node = e.item.getModel();
const nodeName = e.item.getModel().tbl_name;
if (nodeName) {
let formatedNodeName = `<div>表名:${node.tbl_name}<br/>节点ID:${node.id}<br/>集群ID:${node.clust_name}<br/>表ID:${node.tbl_id}</div>`;
// console.log('eeeeeeeeeeee', e, nodeName, formatedNodeName);
outDiv.innerHTML = `${formatedNodeName}`;
return outDiv;
}
},
});
const graph = new G6.Graph({
...
plugins: [tooltip],
});
如需要了解如何监听节点以及边的各种鼠标事件例如点击、覆盖、离开等,请查看以下完整代码示例:
二、完整代码
import G6 from "@antv/g6";
import insertCss from "insert-css";
import { useEffect, useState } from "react";
import { connect } from "umi";
// import constants from '../../constants';
// const COLORS = constants.COLORS;
function SwdtShowHidden(props) {
const { dispatch, relaData = {}, id, nodeInfo = [], edgesInfo = [] } = props;
const globalFontSize = 12;
let nodeSize = 80;
useEffect(() => {
// const data = {
// nodes: [
// {
// id: '0',
// label: '0',
// },
// {
// id: '1',
// label: '1',
// },
// {
// id: '2',
// label: '2',
// },
// {
// id: '3',
// label: '3',
// },
// {
// id: '4',
// label: '4',
// },
// {
// id: '5',
// label: '5',
// },
// {
// id: '6',
// label: '6',
// },
// {
// id: '7',
// label: '7',
// },
// {
// id: '8',
// label: '8',
// },
// {
// id: '9',
// label: '9',
// },
// ],
// edges: [
// {
// source: '0',
// target: '1',
// },
// {
// source: '0',
// target: '2',
// },
// {
// source: '0',
// target: '3',
// },
// {
// source: '0',
// target: '4',
// },
// {
// source: '0',
// target: '5',
// },
// {
// source: '0',
// target: '7',
// },
// {
// source: '0',
// target: '8',
// },
// {
// source: '0',
// target: '9',
// },
// {
// source: '2',
// target: '3',
// },
// {
// source: '4',
// target: '5',
// },
// {
// source: '4',
// target: '6',
// },
// {
// source: '5',
// target: '6',
// },
// ],
// };
const container = document.getElementById(`container${id}`);
const width = container.scrollWidth;
const height = container.scrollHeight || 500;
insertCss(`
.g6-component-tooltip {
background-color: rgba(0,0,0, 0.65);
padding: 10px;
box-shadow: rgb(174, 174, 174) 0px 0px 10px;
width: fit-content;
color: #fff;
border-radius = 4px;
}
.g6-tooltip {
border: 1px solid #e2e2e2;
border-radius: 4px;
font-size: 12px;
color: #545454;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px 8px;
box-shadow: rgb(174, 174, 174) 0px 0px 10px;
}
`);
const tooltip = new G6.Tooltip({
// offsetX and offsetY include the padding of the parent container
offsetX: 20,
offsetY: 30,
// the types of items that allow the tooltip show up
// 允许出现 tooltip 的 item 类型
itemTypes: ["node"],
// custom the tooltip's content
// 自定义 tooltip 内容
getContent: (e) => {
const outDiv = document.createElement("div");
//outDiv.style.padding = '0px 0px 20px 0px';
const node = e.item.getModel();
const nodeName = e.item.getModel().tbl_name;
if (nodeName) {
let formatedNodeName = `<div>表名:${node.tbl_name}<br/>节点ID:${node.id}<br/>集群ID:${node.clust_name}<br/>表ID:${node.tbl_id}</div>`;
// console.log('eeeeeeeeeeee', e, nodeName, formatedNodeName);
outDiv.innerHTML = `${formatedNodeName}`;
return outDiv;
}
},
});
const graph = new G6.Graph({
container: `container${id}`,
width,
height,
plugins: [tooltip],
layout: {
type: "force",
preventOverlap: true,
nodeSize: nodeSize + 50,
},
fitCenter: true,
modes: {
default: [
"drag-node",
"zoom-canvas",
"drag-canvas",
// {
// type: 'tooltip',
// formatText: function formatText(model) {
// // var text = 'description: ' + model.description;
// let str = '';
// nodeInfo.forEach((it) => {
// if (it.id === model.id) {
// str = it.description;
// }
// });
// var text = str;
// return text;
// },
// shouldUpdate: function shouldUpdate(e) {
// return true;
// },
// },
{
type: "edge-tooltip",
formatText: function formatText(model) {
let str = "";
edgesInfo.forEach((it) => {
let mId = model.start + ":" + model.end;
if (it.id === mId) {
str = it.description;
}
});
var text = str;
return text;
},
shouldUpdate: function shouldUpdate(e) {
return true;
},
},
],
},
defaultNode: {
// type: 'rect',
size: [nodeSize, 40],
labelCfg: {
style: {
fontSize: globalFontSize,
},
},
},
defaultEdge: {
type: "cubic-horizontal",
style: {
stroke: "#CED4D9",
endArrow: true,
// endArrow: {
// path: G6.Arrow.vee(10, 20, 10),
// d: 10,
// },
},
},
});
/**
* format the string
* @param {string} str The origin string
* @param {number} maxWidth max width
* @param {number} fontSize font size
* @return {string} the processed result
*/
const fittingString = (str, maxWidth, fontSize) => {
const ellipsis = "...";
const ellipsisLength = G6.Util.getTextSize(ellipsis, fontSize)[0];
let currentWidth = 0;
let res = str;
const pattern = new RegExp("[\u4E00-\u9FA5]+"); // distinguish the Chinese charactors and letters
if (str) {
str.split("").forEach((letter, i) => {
if (currentWidth > maxWidth - ellipsisLength) return;
if (pattern.test(letter)) {
// Chinese charactors
currentWidth += fontSize;
} else {
// get the width of single letter according to the fontSize
currentWidth += G6.Util.getLetterWidth(letter, fontSize);
}
if (currentWidth > maxWidth - ellipsisLength) {
res = `${str.substr(0, i)}${ellipsis}`;
}
});
}
return res;
};
// Modify the label in the data
relaData.nodes &&
relaData.nodes.forEach(function (node) {
node.label = fittingString(node.label, nodeSize, globalFontSize);
});
// relaData.edges.forEach(function (edge) {
// console.log('当前边', edge);
// edge.label = fittingString(edge.label, 120, globalFontSize);
// });
graph.data(relaData);
graph.render();
function refreshDragedNodePosition(e) {
const model = e.item.get("model");
model.fx = e.x;
model.fy = e.y;
}
graph.on("node:dragstart", (e) => {
graph.layout();
refreshDragedNodePosition(e);
});
graph.on("node:drag", (e) => {
refreshDragedNodePosition(e);
});
// 清除节点+边高亮
function clearAllStats() {
graph.setAutoPaint(false);
graph.getNodes().forEach(function (node) {
graph.clearItemStates(node);
});
graph.getEdges().forEach(function (edge) {
graph.clearItemStates(edge);
});
graph.paint();
graph.setAutoPaint(true);
}
// graph.on('edge:click', (e) => {
// console.log('eeeeeeeeee', e);
// });
graph.on("node:mouseenter", function (e) {
var item = e.item;
graph.setAutoPaint(false);
graph.getNodes().forEach(function (node) {
graph.clearItemStates(node);
graph.setItemState(node, "dark", true);
});
graph.setItemState(item, "dark", false);
graph.setItemState(item, "highlight", true);
graph.getEdges().forEach(function (edge) {
if (edge.getSource() === item) {
graph.setItemState(edge.getTarget(), "dark", false);
graph.setItemState(edge.getTarget(), "highlight", true);
graph.setItemState(edge, "highlight", true);
edge.toFront();
} else if (edge.getTarget() === item) {
graph.setItemState(edge.getSource(), "dark", false);
graph.setItemState(edge.getSource(), "highlight", true);
graph.setItemState(edge, "highlight", true);
edge.toFront();
} else {
graph.setItemState(edge, "highlight", false);
}
});
graph.paint();
graph.setAutoPaint(true);
});
graph.on("node:mouseleave", clearAllStats);
graph.on("edge:mouseenter", function (e) {
var item = e.item;
// console.log('移动到边上了', e, item);
graph.setAutoPaint(false);
graph.setItemState(item, "dark", false);
graph.setItemState(item, "highlight", true);
graph.paint();
graph.setAutoPaint(true);
});
graph.on("edge:mouseleave", clearAllStats);
graph.on("canvas:click", clearAllStats);
if (typeof window !== "undefined")
window.onresize = () => {
if (!graph || graph.get("destroyed")) return;
if (!container || !container.scrollWidth || !container.scrollHeight)
return;
graph.changeSize(container.scrollWidth, container.scrollHeight);
};
}, [relaData, id, nodeInfo, edgesInfo]);
return <div id={`container${id}`} style={{ height: "100%" }}></div>;
}
export default connect((store) => {
return {};
})(SwdtShowHidden);