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

如何将沙漏CSS翻转动画转换为SMIL并按指定间隔触发?

把CSS翻转动画转换为SMIL动画的方案

要实现你想要的基于SMIL的沙漏翻转动画,我们可以用SVG原生的<animateTransform>元素替代CSS的@keyframes,完美匹配你需要的“在填充动画总时长最后0.2s触发翻转”的逻辑。下面是具体的实现步骤和修改后的代码:

核心思路

SMIL的<animateTransform>专门用于处理SVG元素的变换动画,我们可以通过values和keyTimes属性精准控制动画的时间节点,完全对应你原来CSS keyframes里的0%、98%、100%三个关键帧:

  • values="0; 0; 180":表示旋转角度从0度保持到98%时间点,最后跳到180度
  • keyTimes="0; 0.98; 1":把动画时长按比例分成三段,对应0%、98%、100%的时间节点
  • 旋转中心通过origin="center center"设置,和CSS的transform-origin: center center效果完全一致

修改后的完整SVG代码

<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="212.17653" height="310" viewBox="0 0 212.17653 310" id="hourglass">
  <defs>
    <clipPath id="flowdown">
      <path d="m 153.09976,190.92975 c 22.09717,217.28036 179.31249,274.21877 197.89215,327.9765 l 62.9374,0 c 18.72854,-53.17156 176.30873,-105.92478 197.9976,-327.99097" style="stroke-width:0" />
    </clipPath>
    <clipPath id="fillup">
      <path d="M 296.23029,608.69417 C 236.36177,663.1914 150.52311,748.96721 150.52311,928.875 l 231.9375,0 231.9375,0 c 0,-181.67405 -83.81727,-266.73823 -143.5691,-320.06035" style="stroke-width:0" />
    </clipPath>
  </defs>
  <!-- 添加SMIL翻转动画到hourglass元素 -->
  <animateTransform
    xlink:href="#hourglass"
    attributeName="transform"
    type="rotate"
    values="0; 0; 180"
    keyTimes="0; 0.98; 1"
    dur="10s"
    begin="0s"
    repeatCount="indefinite"
    origin="center center"
  />
  <g transform="matrix(0.3117516,0,0,0.3117516,-13.144444,-11.10242)" id="layer1">
    <g transform="translate(14,-26)" id="g4027">
      <rect width="648.51801" height="43.605999" x="44.201607" y="-1039.9561" transform="scale(1,-1)" id="rect3782" style="fill:#000000;fill-opacity:1;stroke:none" />
      <rect width="579.82764" height="60" x="78.546791" y="-999.65149" transform="scale(1,-1)" id="rect3784" style="fill:#000000;fill-opacity:1;stroke:none" />
    </g>
    <path d="m 150.53125,138.59375 c 0,276.24024 202.375,328.98438 202.375,390.46875 0,1.83297 -1.12281,3.21907 -0.71875,4.6875 -0.40197,1.4611 0.71875,2.83465 0.71875,4.65625 0,59.91583 -202.375,114.22851 -202.375,390.46875 l 231.9375,0 231.9375,0 c 0,-282.29589 -202.375,-331.32933 -202.375,-390.46875 0,-1.8216 1.12072,-3.19515 0.71875,-4.65625 0.40406,-1.46843 -0.71875,-2.85453 -0.71875,-4.6875 0,-61.32924 202.375,-108.17286 202.375,-390.46875 l -231.9375,0 z" id="path3788" style="fill:none;stroke:#000000;stroke-width:30;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
    <g transform="translate(14,-26)" id="g4043">
      <rect width="648.51801" height="43.605999" x="44.201607" y="77.651443" id="rect4033" style="fill:#000000;fill-opacity:1;stroke:none" />
      <rect width="579.82764" height="60" x="78.546791" y="117.95601" id="rect4035" style="fill:#000000;fill-opacity:1;stroke:none" />
    </g>
    <g clip-path="url(#flowdown)">
      <rect width="744.09448" height="1052.3622" x="0" y="0" id="upper-fill-clip">
        <animate xlink:href="#upper-fill-clip" attributeName="y" from ="190" to="519" dur="10s" begin="0s" repeatCount="indefinite" />
      </rect>
    </g>
    <g clip-path="url(#fillup)" >
      <rect width="744.09448" height="1052.3622" x="0" y="0" id="lower-fill-clip">
        <animate xlink:href="#lower-fill-clip" attributeName="y" from ="911" to="610" dur="10s" begin="0s" repeatCount="indefinite" />
      </rect>
    </g>
  </g>
</svg>

关键参数说明

  • dur="10s":必须和填充动画的dur保持一致(比如你示例里的10s),这样翻转动画的时间节点才能精准对应填充动画的最后0.2s。如果后续要修改填充时长,只要同步修改这个值即可(比如改成5s,会自动在4.8s时触发翻转)。
  • keyTimes="0; 0.98; 1":0.98是计算出来的比例((总时长-0.2)/总时长),比如10s的话,0.98*10=9.8s,刚好是最后0.2s的起始点。
  • origin="center center":确保沙漏围绕中心旋转,和CSS的transform-origin效果完全一致。
  • repeatCount="indefinite":让动画无限循环,和填充动画的循环逻辑同步。

这样修改后,你就完全用SMIL实现了所有动画,不需要依赖CSS,而且完美实现了“填充动画最后0.2s触发翻转”的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:14:05