本文将详细介绍如何利用 Chart.js 的 onHover 事件回调函数,在用户悬停饼图扇区时实时更新页面上独立显示的资产名称与对应数值,从而打造交互式数据展示体验。
在数据可视化领域,悬停交互是提升用户体验的经典手段。Chart.js 作为前端数据可视化的热门库,提供了众多内置事件钩子,其中 onHover 回调尤为重要。它允许开发者在用户鼠标滑过图表元素时执行定制化的更新逻辑——无需刷新页面、无需额外点击,只需轻轻移动鼠标,数据即可直接映射到信息面板的对应位置。
先梳理几个关键点:虽然这个方案比较常见,但要想写得简洁、解耦且易于复用,仍值得仔细推敲。尤其是饼图这种通过扇区表示占比关系的图表,在悬停时反馈具体数值和标签,是非常自然的交互流程。
具体如何实现?来看以下完整代码(适配 Chart.js 3.9+ 版本):
const chart = document.getElementById('chart');new Chart(chart, { type: 'doughnut', data: { labels: ['Bitcoin', 'Ethereum', 'Litecoin', 'Tether'], datasets: [{ data: [50, 30, 10, 10], backgroundColor: [ 'orange', 'purple', 'darkblue', 'green' ], borderWidth: 2, }] }, options: { responsive: false, cutout: '72%', plugins: { legend: { display: false } }, onHover: (event, activeElements) => { // 确保有悬停目标且非空 if (!activeElements || activeElements.length === 0) return; const firstActive = activeElements[0]; const labelEl = document.querySelector('.chart-asset-type'); const valueEl = document.querySelector('.chart-asset-value'); if (!labelEl || !valueEl) return; const label = event.chart.data.labels[firstActive.index]; const value = event.chart.data.datasets[firstActive.datasetIndex].data[firstActive.index]; // 可选:格式化数值(如添加货币符号) labelEl.textContent = label; valueEl.textContent = `$${value.toLocaleString()}`; } }});配套的 HTML 结构也至关重要,它需要足够简洁,同时确保 .chart-balance 区域与 canvas 保持同级,并通过 CSS 定位实现叠加显示:
Ethereum
$1,000
CSS 方面建议补充基础样式,核心目标是让叠加层精确定位:
.chart-wrap { position: relative; width: 224px; height: 224px; margin: 0 auto;}.chart-balance { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); text-align: center; pointer-events: none; /* 防止遮挡 canvas 悬停事件 */}不过,有几个细节需要特别注意:
- onHover 回调中的 activeElements 是一个数组,即使只悬停在一个扇区上,也需通过 [0] 获取当前活跃元素;
- 推荐使用 document.querySelector() 获取元素,它比 getElementsByClassName() 语义更清晰,返回单一元素,操作更省心;
- 如果项目需要在移动端支持触摸悬停,可以额外监听 onTouchStart 事件,或启用 interaction.mode: 'nearest' 配置进行触控适配;
- 数据值如果是金额、百分比等有格式要求的字段,最好在赋值前先做格式化处理,能显著提升用户体验。
这个方案思路轻量,核心逻辑与 DOM 更新完全解耦。而且它不限于饼图——bar、line、pie 等所有 Chart.js 支持的图表类型均可适用,只需根据实际数据结构微调索引访问逻辑即可。
