React中Chart.js外部Tooltip设置垂直滚动失效问题求助
在React中为Chart.js实现可滚动外部Tooltip的问题
我需要在React中给Chart.js的Tooltip添加垂直滚动功能,因为要展示大量数据。已经参考官方文档创建了外部HTML Tooltip,并且给tooltipEl添加了max-height和overflow-y样式,但这些样式没有生效,想问下是不是没办法实现Tooltip垂直滚动?
const getOrCreateTooltip = (chart: any) => { let tooltipEl = chart.canvas.parentNode.querySelector("div"); if (!tooltipEl) { tooltipEl = document.createElement("div"); tooltipEl.style.background = "rgba(0, 0, 0, 0.7)"; tooltipEl.style.borderRadius = "3px"; tooltipEl.style.color = "white"; tooltipEl.style.opacity = 1; tooltipEl.style.pointerEvents = "none"; tooltipEl.style.position = "absolute"; tooltipEl.style.transform = "translate(-50%, 0)"; tooltipEl.style.transition = "all .1s ease"; const table = document.createElement("table"); table.style.margin = "0px"; tooltipEl.appendChild(table); chart.canvas.parentNode.appendChild(tooltipEl); } return tooltipEl; }; const externalTooltipHandler = (context: any) => { // Tooltip Element const { chart, tooltip } = context; const tooltipEl = getOrCreateTooltip(chart); // Hide if no tooltip if (tooltip.opacity === 0) { tooltipEl.style.opacity = 0; return; } // Set Text if (tooltip.body) { const titleLines = tooltip.title || []; const bodyLines = tooltip.body.map((b: any) => b.lines); const tableHead = document.createElement("thead"); titleLines.forEach((title: any) => { const tr = document.createElement("tr"); tr.style.borderWidth = "0"; const th = document.createElement("th"); th.style.borderWidth = "0"; const text = document.createTextNode(title); th.appendChild(text); tr.appendChild(th); tableHead.appendChild(tr); }); const tableBody = document.createElement("tbody"); bodyLines.forEach((body: any, i: any) => { const colors = tooltip.labelColors[i]; const span = document.createElement("span"); span.style.background = colors.backgroundColor; span.style.borderColor = colors.borderColor; span.style.borderWidth = "2px"; span.style.marginRight = "10px"; span.style.height = "10px"; span.style.width = "10px"; span.style.display = "inline-block"; const tr = document.createElement("tr"); tr.style.fontSize = "14px"; tr.style.backgroundColor = "inherit"; tr.style.borderWidth = "0"; const td = document.createElement("td"); td.style.borderWidth = "0"; const text = document.createTextNode(body); td.appendChild(span); td.appendChild(text); tr.appendChild(td); tableBody.appendChild(tr); }); const tableRoot = tooltipEl.querySelector("table"); while (tableRoot.firstChild) { tableRoot.firstChild.remove(); } tableRoot.appendChild(tableHead); tableRoot.appendChild(tableBody); } const { offsetLeft: positionX, offsetTop: positionY } = chart.canvas; tooltipEl.style.opacity = 1; tooltipEl.style.left = positionX + tooltip.caretX + "px"; tooltipEl.style.top = positionY + tooltip.caretY + "px"; tooltipEl.style.font = tooltip.options.bodyFont.string; tooltipEl.style.padding = tooltip.options.padding + "px " + tooltip.options.padding + "px"; tooltipEl.style.maxHeight = "330px"; tooltipEl.style.overflowY = "auto"; tooltipEl.style.zIndex = 1000; }; const options = { maintainAspectRatio: false, scales: { x: { offset: true, grid: { drawTicks: false, offset: true, color: "#00001A26", }, ticks: { color: "rgba(0 ,0 ,0 ,0.7)", padding: 4, stepSize: 1, font: { size: 12, }, }, border: { dash: [2, 2], }, min: -3, max: 3, }, y: { beginAtZero: true, grid: { drawTicks: false, color: "#00001A26", }, ticks: { color: "rgba(0 ,0 ,0 ,0.7)", padding: 4, maxTicksLimit: 5, font: { size: 12, }, }, border: { dash: [2, 2], display: false, }, }, }, plugins: { tooltip: { enabled: false, external: externalTooltipHandler, }, }, };
解决方法
你的问题主要有两个核心原因:
pointerEvents: none会阻止鼠标在Tooltip上触发滚动事件,导致滚动交互失效- 内部的
<table>元素默认布局会直接撑开Tooltip容器,让外层的max-height限制不生效
修改步骤:
- 启用鼠标交互:将tooltipEl的
pointerEvents从none改为auto,让鼠标能在Tooltip上触发滚动 - 限制表格高度:给内部的table设置
display: block和max-height,让表格内容在超出时滚动,同时不撑开外层容器
修改后的代码片段:
调整getOrCreateTooltip函数:
const getOrCreateTooltip = (chart: any) => { let tooltipEl = chart.canvas.parentNode.querySelector("div"); if (!tooltipEl) { tooltipEl = document.createElement("div"); tooltipEl.style.background = "rgba(0, 0, 0, 0.7)"; tooltipEl.style.borderRadius = "3px"; tooltipEl.style.color = "white"; tooltipEl.style.opacity = 1; // 允许鼠标交互,才能触发滚动 tooltipEl.style.pointerEvents = "auto"; tooltipEl.style.position = "absolute"; tooltipEl.style.transform = "translate(-50%, 0)"; tooltipEl.style.transition = "all .1s ease"; tooltipEl.style.maxHeight = "330px"; tooltipEl.style.overflowY = "auto"; tooltipEl.style.zIndex = 1000; const table = document.createElement("table"); table.style.margin = "0px"; // 让表格支持滚动,高度减去上下padding值 table.style.display = "block"; table.style.maxHeight = `calc(100% - ${tooltip.options.padding * 2}px)`; table.style.overflowY = "auto"; // 可选:优化滚动条样式 table.style.scrollbarWidth = "thin"; table.style.scrollbarColor = "#fff rgba(0,0,0,0.3)"; tooltipEl.appendChild(table); chart.canvas.parentNode.appendChild(tooltipEl); } return tooltipEl; };
简化externalTooltipHandler中的重复样式:
移除已经在创建阶段设置过的重复样式:
// 移除以下重复代码 // tooltipEl.style.maxHeight = "330px"; // tooltipEl.style.overflowY = "auto"; // tooltipEl.style.zIndex = 1000;
修改完成后,Tooltip就能正常实现垂直滚动,同时不会影响Chart.js的其他交互(比如鼠标悬停高亮)。
内容的提问来源于stack exchange,提问作者Ji Yeon Kim
相关产品推荐
相关产品推荐

