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

如何用SMIL或CSS实现SVG渐变条从左至右填充并冻结状态?

嘿,我来帮你搞定这个条形图的渐变动画需求!不管是用SMIL还是CSS动画,都能实现你要的“从左到右、从无颜色过渡到多色渐变,最后冻结状态”的效果,下面分别给你详细方案和代码示例:

一、用SMIL实现的方案

SMIL是SVG原生的动画规范,正好适合处理SVG条形图的渐变动画。核心思路是通过动画渐变停止点(<stop>)的offset属性,让渐变从左到右逐步展开,最后用fill="freeze"固定最终状态。

完整代码示例

<svg width="400" height="100" viewBox="0 0 400 100">
  <!-- 定义渐变:初始所有stop的offset都是0(相当于无颜色) -->
  <linearGradient id="barGradient" x1="0%" y1="0%" x2="100%" y2="0%">
    <stop offset="0%" stop-color="#ff6b6b" stop-opacity="0">
      <!-- 动画:offset从0%过渡到25%,持续1s,结束后冻结 -->
      <animate attributeName="offset" from="0%" to="25%" dur="1s" fill="freeze" />
      <animate attributeName="stop-opacity" from="0" to="1" dur="1s" fill="freeze" />
    </stop>
    <stop offset="0%" stop-color="#4ecdc4" stop-opacity="0">
      <animate attributeName="offset" from="0%" to="50%" dur="1s" fill="freeze" />
      <animate attributeName="stop-opacity" from="0" to="1" dur="1s" fill="freeze" />
    </stop>
    <stop offset="0%" stop-color="#45b7d1" stop-opacity="0">
      <animate attributeName="offset" from="0%" to="75%" dur="1s" fill="freeze" />
      <animate attributeName="stop-opacity" from="0" to="1" dur="1s" fill="freeze" />
    </stop>
    <stop offset="0%" stop-color="#96ceb4" stop-opacity="0">
      <animate attributeName="offset" from="0%" to="100%" dur="1s" fill="freeze" />
      <animate attributeName="stop-opacity" from="0" to="1" dur="1s" fill="freeze" />
    </stop>
  </linearGradient>

  <!-- 条形图 -->
  <rect x="20" y="20" width="360" height="60" fill="url(#barGradient)" />
</svg>

关键说明

  • 初始状态下,所有渐变停止点的offset都是0%且stop-opacity为0,相当于条形图完全无颜色;
  • 给每个<stop>添加两个SMIL动画:一个改变offset到目标位置,另一个改变stop-opacity到1,让颜色逐步显现;
  • fill="freeze"是核心属性,它会让动画结束后保持最后一帧的状态,也就是你要的“冻结渐变颜色”效果;
  • 所有动画的dur(持续时间)保持一致,保证渐变同步展开。

二、用CSS动画实现的方案

当然也可以用CSS动画来实现,不需要依赖SMIL,兼容性也不错。这里提供两种思路,推荐第二种更直观的方案:

方案1:动画渐变停止点的位置

利用CSS @keyframes直接修改渐变的停止点位置,配合animation-fill-mode: forwards保持最终状态:

<div class="bar"></div>

<style>
.bar {
  width: 360px;
  height: 60px;
  margin: 20px;
  /* 初始渐变:所有stop都在0位置,透明 */
  background: linear-gradient(to right, 
    #ff6b6b 0%, #ff6b6b 0%,
    #4ecdc4 0%, #4ecdc4 0%,
    #45b7d1 0%, #45b7d1 0%,
    #96ceb4 0%, #96ceb4 0%);
  /* 动画:持续1s,结束后保持最后状态 */
  animation: gradientExpand 1s forwards;
}

@keyframes gradientExpand {
  to {
    background: linear-gradient(to right, 
      #ff6b6b 0%, #ff6b6b 25%,
      #4ecdc4 25%, #4ecdc4 50%,
      #45b7d1 50%, #45b7d1 75%,
      #96ceb4 75%, #96ceb4 100%);
  }
}
</style>

方案2:用clip-path实现从左到右的展开效果

这种思路更灵活,先给条形图设置好完整的渐变背景,然后通过动画clip-path的右侧裁剪区域,让渐变从左到右逐步显示:

<div class="bar"></div>

<style>
.bar {
  width: 360px;
  height: 60px;
  margin: 20px;
  /* 预先设置好完整的多色渐变 */
  background: linear-gradient(to right, 
    #ff6b6b 25%, 
    #4ecdc4 25%, #4ecdc4 50%,
    #45b7d1 50%, #45b7d1 75%,
    #96ceb4 75%);
  /* 初始裁剪:只显示左侧0宽度的区域 */
  clip-path: inset(0 100% 0 0);
  /* 动画:裁剪区域从右侧100%变为0,持续1s,结束后保持状态 */
  animation: slideIn 1s forwards;
}

@keyframes slideIn {
  to {
    clip-path: inset(0 0 0 0);
  }
}
</style>

CSS方案关键说明

  • animation-fill-mode: forwards是实现“冻结状态”的核心,它会让元素在动画结束后保持@keyframes里to的状态;
  • 方案2的优势是渐变本身是固定的,只需要控制显示区域,代码更简洁,也更容易调整动画速度和方向。

内容的提问来源于stack exchange,提问作者S. Schenk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:54:42