如何实现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'; });
关键解决逻辑说明
- 拆分元素层级:把扇区和中心内容分成两个独立的
<g>组,中心组写在扇区组之后(SVG中后定义的元素层级更高),确保鼠标悬停中心时不会触发下方扇区的hover事件。 - 精准样式作用范围:用
.pie-sectors:hover .sector:not(:hover)选择器,仅让扇区组内的非悬停扇区变暗,完全不影响中心文本的显示。 - 事件隔离:给中心组设置
pointer-events: all,强制中心元素接收鼠标事件,避免事件冒泡到下方扇区。 - 文本切换逻辑:通过JS监听扇区的鼠标事件,精准切换对应文本;悬停中心圆形时直接恢复默认状态,逻辑清晰且易维护。
内容的提问来源于stack exchange,提问作者David Headrick
相关产品推荐
相关产品推荐

