
本文介绍如何利用 Chart.js 的 onHover 事件钩子,实现在环形图(doughnut chart)上悬停不同扇区时,实时更新页面中独立 DOM 元素(如资产名称和数值)的内容,提升交互体验。
本文介绍如何利用 chart.js 的 `onhover` 事件钩子,实现在环形图(doughnut chart)上悬停不同扇区时,实时更新页面中独立 dom 元素(如资产名称和数值)的内容,提升交互体验。
在 Chart.js 中,onHover 是一个强大的配置选项,允许开发者监听鼠标悬停行为,并基于当前高亮的数据点动态更新界面。与传统的 tooltip 自定义不同,该方案将数据联动延伸至图表外部的任意 HTML 元素——例如本例中位于画布上方的 .chart-balance 区域。
以下为完整实现步骤与优化后的代码:
详细的 Three.js 3D 图形参考,涵盖场景设置、相机、几何体、材质、光照、动画、控制器、加载器、数学工具和调试。
✅ 核心逻辑说明
- onHover 回调接收两个参数:evt(事件对象)和 activeEls(当前激活的数据元素数组);
- 当 activeEls.length === 0 时,表示鼠标已移出所有数据区域,可选择清空或保留默认值;
- 通过 activeEls[0].index 获取当前悬停扇区在 labels 和 data 数组中的索引,从而精准提取对应标签与数值;
- 使用原生 DOM 方法(如 getElementsByClassName)定位并更新目标元素内容,无需额外依赖。
? 完整可运行代码示例
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script><div class="chart-wrap">
<canvas id="chart" width="224" height="224"></canvas><div class="chart-balance">
<p class="chart-asset-type">Ethereum</p>
<h5 class="chart-asset-value">$1,000</h5>
</div>
</div>
<style>
.chart-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 224px;
height: 224px;
}
.chart-balance {
position: absolute;
text-align: center;
pointer-events: none; /* 防止遮挡 canvas 悬停事件 */
}
.chart-asset-type {
margin: 0;
font-size: 14px;
color: #333;
}
.chart-asset-value {
margin: 4px 0 0;
font-size: 18px;
font-weight: bold;
color: #2c3e50;
}
</style><script>
const ctx = document.getElementById('chart').getContext('2d');
const chart = new Chart(ctx, {
type: 'doughnut',
data: {
labels: ['Bitcoin', 'Ethereum', 'Litecoin', 'Tether'],
datasets: [{
data: [50, 30, 10, 10],
backgroundColor: [
'orange',
'purple',
'darkblue',
'green'
],
borderWidth: 2,
}]
},
options: {
responsive: false,
maintainAspectRatio: false,
cutout: '72%',
plugins: {
legend: { display: false }
},
onHover: (evt, activeEls) => {
if (activeEls.length === 0) return;
const labelEl = document.querySelector('.chart-asset-type');
const valueEl = document.querySelector('.chart-asset-value');
const { index } = activeEls[0];
const label = evt.chart.data.labels[index];
const value = evt.chart.data.datasets[0].data[index];
labelEl.textContent = label;
valueEl.textContent = `$${value.toLocaleString()}`;
}
}
});
</script>
⚠️ 注意事项与最佳实践
- 性能考虑:避免在 onHover 中执行复杂计算或频繁 DOM 操作;本例使用 textContent 替代 innerHTML 更安全高效;
- 样式兼容性:.chart-balance 建议添加 pointer-events: none,防止其遮挡 canvas 导致悬停中断;
- 响应式适配:若需支持响应式布局,请将 responsive: true 并移除固定宽高,同时用 CSS 控制容器尺寸;
- 空状态处理:可在 activeEls.length === 0 分支中还原初始文案或隐藏 .chart-balance,增强用户体验连贯性。
通过上述方式,你不仅能实现“悬停即显”的轻量级交互效果,还能灵活扩展为展示更多维度数据(如百分比、变化率、图标等),为金融仪表盘、数据看板等场景提供专业级可视化支持。










