You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

求助:实现SVG双层空心三角形间隙从下到上的填充动画

解决方案:用SVG遮罩(Mask)实现间隙填充动画

你遇到的问题核心是:直接填充现有的<polygon>会覆盖内层三角形,因为它们是独立的元素——我们需要把填充区域严格限制在两个三角形的间隙范围内,而不是填充整个多边形。

这里推荐使用SVG的<mask>特性来定义可填充的区域,再配合一个动画元素实现从下到上的填充效果,具体实现如下:

完整代码示例

<!DOCTYPE html>
<html>
<head>
  <style>
    body{ background: #7085EA; }
    .triangle-container{ width: 500px; margin: auto; text-align:center; }
    .triangle { stroke: #fff; fill: transparent; }
    
    /* 用CSS动画实现填充效果,更灵活可控 */
    #fill-shape {
      animation: fillUp 3s ease-in-out infinite;
    }
    
    @keyframes fillUp {
      0% {
        transform: translateY(0);
      }
      100% {
        transform: translateY(-300px);
      }
    }
  </style>
</head>
<body>
<div class="triangle-container">
<svg height="500" width="500">
  <!-- 定义遮罩:仅允许大三角形减去小三角形的区域显示填充内容 -->
  <mask id="triangle-gap-mask">
    <!-- 黑色背景:默认隐藏所有区域 -->
    <rect width="100%" height="100%" fill="black"/>
    <!-- 白色大三角形:允许显示该区域 -->
    <polygon points="250,100 100,400 400,400" fill="white"/>
    <!-- 黑色小三角形:在大三角形区域内挖空,形成间隙 -->
    <polygon points="250,180 160,360 340,360" fill="black"/>
  </mask>
  
  <!-- 保留原有的两个空心三角形 -->
  <polygon points="250,100 100,400 400,400" class="triangle"/>
  <polygon points="250,180 160,360 340,360" class="triangle"/>
  
  <!-- 填充用的矩形:被遮罩限制在间隙区域,做向上移动动画 -->
  <rect id="fill-shape" x="100" y="400" width="300" height="300" fill="#fff" mask="url(#triangle-gap-mask)"/>
</svg>
</div>
</body>
</html>

核心原理说明

  • 遮罩(Mask)的作用
    遮罩中black代表隐藏区域,white代表显示区域。我们先设置全黑背景,再用白色大三角形“解锁”显示范围,最后用黑色小三角形在这个范围内挖空,精准得到两个三角形之间的间隙作为可填充区域。
  • 动画实现
    用一个覆盖大三角形的矩形作为填充元素,通过transform: translateY()让它从底部(y=400)向上移动到顶部(y=100),配合遮罩就只会显示间隙里的部分,形成从下到上填充的视觉效果。
  • 保留镂空效果
    原有的两个空心三角形始终在最上层,不会被填充元素覆盖,完美保留了初始的镂空样式。

可选优化

  • 调整动画的timing-function(比如ease-in让填充速度逐渐变慢),可以获得更自然的视觉效果;
  • 也可以用SVG原生的<animate>标签替代CSS动画,直接写在<rect>内部:
    <rect id="fill-shape" x="100" y="400" width="300" height="300" fill="#fff" mask="url(#triangle-gap-mask)">
      <animate attributeName="y" from="400" to="100" dur="3s" repeatCount="indefinite" />
    </rect>
    

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

火山引擎 最新活动