You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现SVG饼图扇区悬停时局部变暗与中心文本切换

解决SVG饼图交互问题的具体方案

核心问题拆解

你遇到的问题本质是元素层级与样式作用范围冲突,以及事件触发逻辑的精准控制。下面直接给出可落地的代码方案和关键说明:


完整实现代码

SVG结构(拆分扇区与中心内容层级)

<svg viewBox="0 0 200 200" width="200">
  <!-- 饼图扇区组:单独存放所有扇区,样式仅作用于此组 -->
  <g class="pie-sectors">
    <path class="sector" d="M100,100 L100,0 A100,100 0 0,1 170.71,70.71 Z" fill="#ff4444"/>
    <path class="sector" d="M100,100 L170.71,70.71 A100,100 0 0,1 100,200 Z" fill="#44ff44"/>
    <path class="sector" d="M100,100 L100,200 A100,100 0 0,1 29.29,129.29 Z" fill="#4444ff"/>
    <path class="sector" d="M100,100 L29.29,129.29 A100,100 0 0,1 100,0 Z" fill="#ffff44"/>
  </g>
  <!-- 中心内容组:层级在扇区之上,不受扇区样式影响 -->
  <g class="center-content">
    <circle cx="100" cy="100" r="40" fill="#ffffff"/>
    <text class="center-text default" x="100" y="105" text-anchor="middle">Hover a sector</text>
    <text class="center-text red" x="100" y="105" text-anchor="middle" style="display:none">Red Sector</text>
    <text class="center-text green" x="100" y="105" text-anchor="middle" style="display:none">Green Sector</text>
    <text class="center-text blue" x="100" y="105" text-anchor="middle" style="display:none">Blue Sector</text>
    <text class="center-text yellow" x="100" y="105" text-anchor="middle" style="display:none">Yellow Sector</text>
  </g>
</svg>

CSS样式(精准控制扇区变暗逻辑)

/* 扇区默认过渡效果 */
.sector {
  transition: filter 0.3s ease;
  cursor: pointer;
}

/* 悬停扇区时,其余兄弟扇区变暗(仅作用于扇区组内元素) */
.pie-sectors:hover .sector:not(:hover) {
  filter: opacity(0.5);
}

/* 中心内容组:强制接收鼠标事件,避免触发下方扇区的hover */
.center-content {
  pointer-events: all;
}

.center-content circle {
  cursor: default;
}

JavaScript(处理文本切换与状态恢复)

const sectors = document.querySelectorAll('.sector');
const centerTexts = document.querySelectorAll('.center-text');
const defaultText = document.querySelector('.center-text.default');

// 扇区悬停时切换对应文本
sectors.forEach((sector, index) => {
  sector.addEventListener('mouseenter', () => {
    centerTexts.forEach(text => text.style.display = 'none');
    centerTexts[index + 1].style.display = 'block';
  });

  sector.addEventListener('mouseleave', () => {
    centerTexts.forEach(text => text.style.display = 'none');
    defaultText.style.display = 'block';
  });
});

// 悬停中心圆形时,恢复所有扇区状态与默认文本
document.querySelector('.center-content circle').addEventListener('mouseenter', () => {
  sectors.forEach(sector => sector.style.filter = 'none');
  centerTexts.forEach(text => text.style.display = 'none');
  defaultText.style.display = 'block';
});

关键解决逻辑说明

  1. 拆分元素层级:把扇区和中心内容分成两个独立的<g>组,中心组写在扇区组之后(SVG中后定义的元素层级更高),确保鼠标悬停中心时不会触发下方扇区的hover事件。
  2. 精准样式作用范围:用.pie-sectors:hover .sector:not(:hover)选择器,仅让扇区组内的非悬停扇区变暗,完全不影响中心文本的显示。
  3. 事件隔离:给中心组设置pointer-events: all,强制中心元素接收鼠标事件,避免事件冒泡到下方扇区。
  4. 文本切换逻辑:通过JS监听扇区的鼠标事件,精准切换对应文本;悬停中心圆形时直接恢复默认状态,逻辑清晰且易维护。

内容的提问来源于stack exchange,提问作者David Headrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 16:22:35