如何实现SVG描边内部区域的自下而上鼠标悬停填充效果?
实现SVG鼠标悬停时从底部到顶部的填充动画
我有一段SVG代码,想要实现鼠标悬停时,描边内部区域从底部到顶部逐渐填充颜色的效果,但自己写的JavaScript代码完全没效果,求解决。
现有SVG代码
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.73 268.03"> <defs> <style>.cls-1{fill:none;stroke:#231f20;stroke-miterlimit:10;stroke-width:6px;}</style> </defs> <path class="cls-1" d="M227.34,231.69c9.24-1.11-85.47,12.9-85.47,12.9l31.28,15c4.65,0,37.16-9.81,37.16-9.81,13.94-5.68,20.13-2.58,20.13-2.58,37.16,9.81,50.29,2.26,50.29,2.26s0-71-62-74.5c-2.24-.13-6.32-3.62-8.28-4.65a235.64,235.64,0,0,0-23.7-10.71,253.36,253.36,0,0,0-36-11.1c-7.16-1.63-14.4-2.95-21.68-3.91-3-.4-7-.13-9.79-1.42-10.27-4.86-7.15-14-10.1-23.45,0,0-2.58-15-5.68-13.94,0,0,.52-17-6.19-21.16,0,0-.52-18.06-4.65-17,0,0-11.35-40.26-26.83-37.68,0,0-5.68-10.32-10.33-9.81,0,0-6.71-2.61-9.8,0,0,0-6.71-2-15-16.5,0,0-10.32,3.1-10.32,6.71L32.25,29.88S30.7,33.49,14.7,20.07c0,0-5.68,3.62-4.13,9.81l4.65,10.84c2.58,1.55-2.59,18.58-2.59,18.58S5.41,76.85,7,82.53l2.58,6.71c-4.13-.52-5.16,5.16-5.16,5.16v27.87s-3.1,16.51,0,20.64c0,0-3.1,8.78,10.32,19.62,0,0,3.61,28.9,13.93,40.25L19.86,227l1,3.62c-4.13,0-3.61,10.32-3.61,10.32,10.87,1,21.78,1.75,32.69,2.17,5.34.21,13.27-1.51,18.29-.36,3.89.89,7.74,6.82,11.12,9.79a87.75,87.75,0,0,0,13.16,9.6c3.42,2,7.64,3.87,11.25,2.19a4.53,4.53,0,0,0,2.47-2.54c.68-2.08-.74-4.22-2.14-5.89a83.43,83.43,0,0,0-36.85-25.28c1.13-4.24,2.46-8.5,3.29-12.79-3.28,11.61,17,16,24.15,17.44,15.47,3,31.55,3.21,47.25,3,12.6-.2,25.18-.89,37.74-1.84C195.38,235.25,211.68,231.69,227.34,231.69Z"/> </svg>
尝试的JavaScript代码
document.addEventListener("DOMContentLoaded", (event) => { console.log("DOM fully loaded and parsed"); const path = document.querySelector("#Layer_2"); console.log(path); path.addEventListener("mouseenter", () => { path.setAttribute("fill", "blue"); console.log("tocaste el lobo"); }); path.addEventListener("mouseleave", () => { path.setAttribute("fill", "transparent"); console.log("saliste del lobo"); }); });
问题分析
- 选择器错误:你选中的是SVG容器(
#Layer_2),但实际控制填充的是内部的<path>元素,且.cls-1类已设置fill:none,CSS类优先级高于SVG元素的fill属性,所以设置SVG的fill不会生效。 - 无动画逻辑:原代码只是直接切换填充色,没有实现从底部到顶部的渐变填充动画。
解决方案
推荐用SVG内置动画+CSS实现,性能更好且无需复杂JS:
修改后的SVG代码(带填充动画)
<svg id="Layer_2" data-name="Layer 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 283.73 268.03"> <defs> <style> .cls-1{ fill: url(#fillGradient); stroke:#231f20; stroke-miterlimit:10; stroke-width:6px; } /* 未hover时隐藏填充 */ .cls-1:not(:hover) { fill: none; } </style> <!-- 定义从下到上的线性渐变动画 --> <linearGradient id="fillGradient" x1="0%" y1="100%" x2="0%" y2="100%"> <stop offset="0%" stop-color="blue" /> <stop offset="0%" stop-color="transparent" /> <!-- hover时填充从底部向上展开 --> <animate attributeName="y2" values="100%;0%" dur="0.6s" begin="mouseenter" fill="freeze" /> <!-- 离开时恢复初始状态 --> <animate attributeName="y2" values="0%;100%" dur="0.6s" begin="mouseleave" fill="freeze" /> </linearGradient> </defs> <path class="cls-1" d="M227.34,231.69c9.24-1.11-85.47,12.9-85.47,12.9l31.28,15c4.65,0,37.16-9.81,37.16-9.81,13.94-5.68,20.13-2.58,20.13-2.58,37.16,9.81,50.29,2.26,50.29,2.26s0-71-62-74.5c-2.24-.13-6.32-3.62-8.28-4.65a235.64,235.64,0,0,0-23.7-10.71,253.36,253.36,0,0,0-36-11.1c-7.16-1.63-14.4-2.95-21.68-3.91-3-.4-7-.13-9.79-1.42-10.27-4.86-7.15-14-10.1-23.45,0,0-2.58-15-5.68-13.94,0,0,.52-17-6.19-21.16,0,0-.52-18.06-4.65-17,0,0-11.35-40.26-26.83-37.68,0,0-5.68-10.32-10.33-9.81,0,0-6.71-2.61-9.8,0,0,0-6.71-2-15-16.5,0,0-10.32,3.1-10.32,6.71L32.25,29.88S30.7,33.49,14.7,20.07c0,0-5.68,3.62-4.13,9.81l4.65,10.84c2.58,1.55-2.59,18.58-2.59,18.58S5.41,76.85,7,82.53l2.58,6.71c-4.13-.52-5.16,5.16-5.16,5.16v27.87s-3.1,16.51,0,20.64c0,0-3.1,8.78,10.32,19.62,0,0,3.61,28.9,13.93,40.25L19.86,227l1,3.62c-4.13,0-3.61,10.32-3.61,10.32,10.87,1,21.78,1.75,32.69,2.17,5.34.21,13.27-1.51,18.29-.36,3.89.89,7.74,6.82,11.12,9.79a87.75,87.75,0,0,0,13.16,9.6c3.42,2,7.64,3.87,11.25,2.19a4.53,4.53,0,0,0,2.47-2.54c.68-2.08-.74-4.22-2.14-5.89a83.43,83.43,0,0,0-36.85-25.28c1.13-4.24,2.46-8.5,3.29-12.79-3.28,11.61,17,16,24.15,17.44,15.47,3,31.55,3.21,47.25,3,12.6-.2,25.18-.89,37.74-1.84C195.38,235.25,211.68,231.69,227.34,231.69Z"/> </svg>
若需用JS控制(仅基础切换,无渐变动画)
document.addEventListener("DOMContentLoaded", () => { // 选中内部的path元素,而非SVG容器 const path = document.querySelector("#Layer_2 .cls-1"); path.addEventListener("mouseenter", () => { // 覆盖CSS类的fill:none path.style.fill = "blue"; path.style.transition = "fill 0.6s ease"; }); path.addEventListener("mouseleave", () => { path.style.fill = "none"; }); });
关键说明
- SVG内置
<animate>标签可直接对渐变属性做动画,性能优于JS操作 - 必须选中
<path>元素而非SVG容器,才能正确控制填充样式 - CSS类优先级高于内联属性,需用内联样式或更高优先级的CSS规则覆盖原有
fill:none
内容的提问来源于stack exchange,提问作者Juan Federico Di Leo
相关产品推荐
相关产品推荐

