如何实现SVG中无父子关系的path与text标签同步CSS hover效果
解决方案
你可以通过以下两种常用方式实现path和text的同步hover效果:
方案1:使用SVG<g>标签分组(推荐,纯CSS无兼容问题)
SVG的<g>是原生分组标签,将对应区域的path和text放在同一个<g>下,直接给<g>设置hover状态样式即可,效果和HTML父元素hover同步子元素完全一致。
修改后的SVG代码:
<svg viewbox="0 0 500 500" xmlns="http://www.w3.org/2000/svg"> <!-- 北区域分组 --> <g class="map-area"> <path id="CD11110" className="OUTLINE CD11110" d="M 455 297 l 4 -2 1 0 1 0 3 -1 4 5 7 3 2 6 0 8 -11 2 -11 1 -8 0 -9 1 -8 1 -9 1 -9 -2 -10 -1 -9 1 -4 3 -2 3 -6 -6 -3 -4 -5 -6 -4 -5 -2 -5 5 -3 0 -6 0 -10 0 -9 1 -9 -3 -4 -2 0 -2 0 -1 -4 0 -9 -5 -9 1 -10 -1 -11 -1 -6 2 -6 5 -2 7 -3 10 -2 2 -1 3 0 1 0 4 -2 8 -1 3 6 4 1 3 8 3 10 1 6 3 5 0 9 0 7 -1 5 -6 3 -6 4 -1 5 6 4 5 3 5 4 9 1 10 0 4 4 3 4 5 10 1 3 z " /> <text id="LCD11110" className="TEXT" x="399" y="277" >north</text> </g> <!-- 中部区域分组 --> <g class="map-area"> <path id="CD11140" className="OUTLINE" d="M 477 316 l 0 9 5 5 -1 3 -4 5 -4 5 -5 4 -4 7 -3 4 -4 3 -4 10 -2 -1 -3 -7 -2 -5 -2 1 -1 0 -2 -1 -3 1 0 0 -3 1 -4 2 -5 -5 -6 -3 -10 -3 -4 -1 -3 -1 -2 2 -4 -1 -3 -1 -9 0 -2 2 -4 3 0 -7 1 -4 -2 -2 0 -1 6 -3 6 -4 -1 -2 -2 -5 2 -3 4 -3 9 -1 10 1 9 2 9 -1 8 -1 9 -1 8 0 11 -1 z " /> <text id="LCD11140" className="TEXT" x="433" y="338">middle</text> </g> <!-- 南部区域分组 --> <g class="map-area"> <path id="CD11170" className="OUTLINE" d="M 394 349 l 3 1 4 1 2 -2 3 1 4 1 10 3 6 3 5 5 4 -2 3 -1 0 0 3 -1 2 1 1 0 2 -1 2 5 3 7 2 1 5 9 6 2 2 9 -4 5 -4 5 -5 6 -3 4 -5 4 -5 5 -5 4 -5 3 -8 8 -5 8 -7 3 -7 -1 -10 -4 -3 -1 -6 -3 -6 -5 -5 -3 -6 -3 -9 -3 1 -5 0 -10 -2 -8 -6 -11 5 -2 4 -1 5 -4 5 -6 2 -5 3 -6 6 -5 0 -3 -2 -3 4 -3 2 -2 z " /> <text id="LCD11170" className="TEXT" x="407" y="395">south</text> </g> </svg>
配套CSS代码:
/* 分组默认样式 */ .map-area { pointer-events: bounding-box; /* 整个分组的包围盒都可触发hover,可选,扩大触发范围 */ } /* hover时同时修改path和text的样式 */ .map-area:hover path { fill: #2563eb; /* 自定义路径hover填充色 */ stroke: #1e40af; /* 自定义路径hover描边色 */ stroke-width: 2; } .map-area:hover text { fill: #fff; /* 自定义文字hover颜色 */ font-weight: bold; }
方案2:不修改原DOM结构,用JS实现
如果不能调整现有SVG的结构,可以通过JS监听hover事件,给对应关联的path和text同步添加激活样式:
// 建立path和text的关联映射 const mapRelation = { 'CD11110': 'LCD11110', 'CD11140': 'LCD11140', 'CD11170': 'LCD11170' } // 反向映射 const reverseRelation = Object.fromEntries(Object.entries(mapRelation).map(([k,v])=>[v,k])) // 绑定hover事件 document.querySelectorAll('.OUTLINE, .TEXT').forEach(el => { el.addEventListener('mouseenter', () => { let pathId, textId if(el.classList.contains('OUTLINE')) { pathId = el.id textId = mapRelation[pathId] } else { textId = el.id pathId = reverseRelation[textId] } // 给两个元素加激活类 document.getElementById(pathId).classList.add('active') document.getElementById(textId).classList.add('active') }) el.addEventListener('mouseleave', () => { let pathId, textId if(el.classList.contains('OUTLINE')) { pathId = el.id textId = mapRelation[pathId] } else { textId = el.id pathId = reverseRelation[textId] } // 移除激活类 document.getElementById(pathId).classList.remove('active') document.getElementById(textId).classList.remove('active') }) })
配套CSS:
.OUTLINE.active { fill: #2563eb; stroke: #1e40af; stroke-width: 2; } .TEXT.active { fill: #fff; font-weight: bold; }
内容的提问来源于stack exchange,提问作者CaliforniaLuv
相关产品推荐
相关产品推荐

