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

如何实现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");
  });
});

问题分析

  1. 选择器错误:你选中的是SVG容器(#Layer_2),但实际控制填充的是内部的<path>元素,且.cls-1类已设置fill:none,CSS类优先级高于SVG元素的fill属性,所以设置SVG的fill不会生效。
  2. 无动画逻辑:原代码只是直接切换填充色,没有实现从底部到顶部的渐变填充动画。

解决方案

推荐用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 07:07:36