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

如何实现矩形填充沿任意对角线方向的clip-path动画?

问题描述

我已经实现了一个clip-path从左到右消失的动画效果:

svg {
  height: 100vh;
}

#myClip {
  animation: anime 2s ease infinite;
}

@keyframes anime {
  0% {
    transform: scaleX(0);
    transform-origin: left center;
  }
  25% {
    transform: scaleX(1);
    transform-origin: left center;
  }
  50% {
    transform: scaleX(1);
    transform-origin: right center;
  }
  100% {
    transform-origin: right center;
    transform: scaleX(0);
  }
}
<svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
  <clipPath id="myClip" clipPathUnits="objectBoundingBox">
    <rect width="1" height="1" />
  </clipPath>
  <rect x="0" width="100" height="100" rx="15" clip-path="url(#myClip)" />
</svg>

现在我希望实现相同的动画,但沿任意角度的对角线方向执行。

类似如下效果,但需要旋转的是clip-path而非图形:

svg {
  height: 100vh;
}

#myClip {
  animation: anime 2s ease infinite;
}

@keyframes anime {
  0% {
    transform: scaleX(0);
    transform-origin: left center;
  }
  25% {
    transform: scaleX(1);
    transform-origin: left center;
  }
  50% {
    transform: scaleX(1);
    transform-origin: right center;
  }
  100% {
    transform-origin: right center;
    transform: scaleX(0);
  }
}
<svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
  <clipPath id="myClip" clipPathUnits="objectBoundingBox">
    <rect width="1" height="1" />
  </clipPath>
  <g transform="rotate(-30 50 50)" clip-path="url(#myClip)">
    <rect transform="rotate(30 50 50)" x="0" width="100" height="100" rx="15"  />
  </g>
</svg>

我已尝试的方法

  • 旋转<rect>元素 - 导致矩形变形:

    svg {
      height: 100vh;
    }
    
    #myClip {
      animation: anime 2s ease infinite;
    }
    
    @keyframes anime {
      0% {
        transform: scaleX(0);
        transform-origin: left center;
      }
      25% {
        transform: scaleX(1);
        transform-origin: left center;
      }
      50% {
        transform: scaleX(1);
        transform-origin: right center;
      }
      100% {
        transform-origin: right center;
        transform: scaleX(0);
      }
    }
    
    <svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
      <clipPath id="myClip" clipPathUnits="objectBoundingBox">
        <rect transform="rotate(30)" width="1" height="1" />
      </clipPath>
      <rect x="0" width="100" height="100" rx="15" clip-path="url(#myClip)" />
    </svg>
    
  • 将scaleX改为scale并修改transform-origin - 未达到预期效果:

    svg {
      height: 100vh;
    }
    
    #myClip {
      animation: anime 2s ease infinite;
    }
    
    @keyframes anime {
      0% {
        transform: scale(0);
        transform-origin: 0 0;
      }
      25% {
        transform: scale(1);
        transform-origin: 0 0;
      }
      50% {
        transform: scale(1);
        transform-origin: 100% 70%;
      }
      100% {
        transform-origin: 100% 70%;
        transform: scale(0);
      }
    }
    
    <svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
      <clipPath id="myClip" clipPathUnits="objectBoundingBox">
        <rect width="1" height="1" />
      </clipPath>
      <rect x="0" width="100" height="100" rx="15" clip-path="url(#myClip)" />
    </svg>
    
  • 用<g>包裹<rect>以实现独立旋转 - 页面内容全部消失:

    svg {
      height: 100vh;
    }
    
    #myClip rect {
      animation: anime 2s ease infinite;
    }
    
    @keyframes anime {
      0% {
        transform: scaleX(0);
        transform-origin: left center;
      }
      25% {
        transform: scaleX(1);
        transform-origin: left center;
      }
      50% {
        transform: scaleX(1);
        transform-origin: right center;
      }
      100% {
        transform-origin: right center;
        transform: scaleX(0);
      }
    }
    
    <svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
      <clipPath id="myClip" clipPathUnits="objectBoundingBox">
        <g>
          <rect width="1" height="1" />
        </g>
      </clipPath>
      <rect x="0" width="100" height="100" rx="15" clip-path="url(#myClip)" />
    </svg>
    

解决方案

核心思路是在clip-path内部对矩形先旋转,再执行缩放动画,同时调整变换原点,确保动画沿指定对角线方向展开/收缩。

实现代码

svg {
  height: 100vh;
}

#clipRect {
  /* 先旋转到目标角度,这里以30度为例 */
  transform: rotate(30deg);
  transform-origin: center;
  animation: diagonalAnime 2s ease infinite;
}

@keyframes diagonalAnime {
  0% {
    /* 缩放X轴,变换原点设为旋转后的左上角 */
    transform: rotate(30deg) scaleX(0);
    transform-origin: 0% 50%;
  }
  25% {
    transform: rotate(30deg) scaleX(1);
    transform-origin: 0% 50%;
  }
  50% {
    transform: rotate(30deg) scaleX(1);
    /* 切换变换原点到旋转后的右上角 */
    transform-origin: 100% 50%;
  }
  100% {
    transform: rotate(30deg) scaleX(0);
    transform-origin: 100% 50%;
  }
}
<svg viewBox="-20 -20 140 140" xmlns="http://www.w3.org/2000/svg">
  <clipPath id="myClip" clipPathUnits="objectBoundingBox">
    <!-- 给clip内的矩形单独设置ID,方便控制动画 -->
    <rect id="clipRect" width="1" height="1" />
  </clipPath>
  <rect x="0" width="100" height="100" rx="15" clip-path="url(#myClip)" />
</svg>

关键说明

  1. 变换顺序:必须先执行rotate再执行scaleX,否则缩放会沿着原始坐标轴方向进行,无法得到对角线效果。
  2. 变换原点调整:旋转后矩形的边角位置发生变化,需要将transform-origin设置为旋转后的对应端点(比如0% 50%对应旋转后的左上角,100% 50%对应旋转后的右上角)。
  3. 任意角度适配:只需修改rotate中的角度值,同时保持transform-origin的百分比设置,即可适配不同的对角线方向。

如果需要沿从左下到右上的对角线动画,只需将旋转角度改为-30deg,并调整变换原点为0% 100%和100% 0%即可:

@keyframes diagonalAnime {
  0% {
    transform: rotate(-30deg) scaleX(0);
    transform-origin: 0% 100%;
  }
  25% {
    transform: rotate(-30deg) scaleX(1);
    transform-origin: 0% 100%;
  }
  50% {
    transform: rotate(-30deg) scaleX(1);
    transform-origin: 100% 0%;
  }
  100% {
    transform: rotate(-30deg) scaleX(0);
    transform-origin: 100% 0%;
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:12:05