Chrome/Chromium 中的 SVG 剪辑路径动画错误

SVG clip-path animation bug in Chrome/Chromium

我是使用 CSS 制作 SVG 动画的新手,我正在尝试创建“眨眼”效果。这是我设法做到的:

https://codepen.io/pablo-m/pen/jOGeMpJ.

(编辑 3:添加代码)

SVG

<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 571.8 761.82">
  <g id="Ojito">
    <rect x="190.37" y="288.55" width="192.7" height="91.76" fill="#606060" />
    <ellipse id="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" fill="#3caa56" />
    <circle id="inner-eye" cx="291.69" cy="334.82" r="18.38" fill="#efefef" />
  </g>
</svg>

SCSS

#composicion {
  #Ojito {
    @keyframes inner-eye-blink {
      0%,
      82%,
      95%,
      100% {
        clip-path: ellipse(75% 55%);
      }
      90% {
        clip-path: ellipse(75% 0);
      }
    }

    @keyframes outer-eye-blink {
      0%,
      80%,
      100% {
        ry: 30.01px;
      }
      90% {
        ry: 1px;
      }
    }

    & #outer-eye {
      animation: outer-eye-blink 8s ease infinite;
    }

    & #inner-eye {
      animation: inner-eye-blink 8s infinite;
    }
  }
}

该动画在 Firefox v95.0.2 和 Safari v15.1 上效果很好。然而,在 Chrome/Chromium v97.0.4692.71(截至今天,最新版本)上它没有。看起来,每当我应用 clip-path 和 css 时,白色的 circle 就会消失。我还注意到这种行为不会发生在 Chrome/Chromium v96.0.4664.93 上。我是在做错什么还是在 Chrome/Chromium 的最新版本中做了一些更改?编辑:如果我做的一切都正确,有人知道解决方法吗?

这是我在 SO 中的第一个问题,所以如果我遗漏了任何细节,请告诉我。

谢谢!

编辑:我查看了 Chromium 的错误跟踪器,但没有发现任何相关问题。

编辑 2:Chromium bug reported

看起来确实是 Chrome 错误。但是,我设法找到了解决问题的解决方法:https://codepen.io/pablo-m/pen/WNZYeoB

SCSS

#composicion {
  #Ojito {
    @keyframes inner-eye-move {
      0%,
      5%,
      20%,
      25%,
      40%,
      45%,
      50%,
      60%,
      65%,
      80%,
      85%,
      100% {
        cx: 291.69px;
        cy: 334.82px;
      }
      10%,
      15% {
        cx: 273.69px;
        cy: 328.82px;
      }
      30%,
      35% {
        cx: 291.69px;
        cy: 342.82px;
      }
      70%,
      75% {
        cx: 310.69px;
        cy: 328.82px;
      }
      90%,
      95% {
        cx: 307.69px;
        cy: 338.82px;
      }
    }

    @keyframes outer-eye-blink {
      0%,
      80%,
      100% {
        ry: 30.01px;
      }
      90% {
        ry: 1px;
      }
    }

    & .outer-eye {
      animation: outer-eye-blink 8s ease infinite;
    }

    & #inner-eye {
      clip-path: url(#eyeClip);
      animation: inner-eye-move 50s ease infinite;
    }
  }
}

SVG

<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 571.8 761.82">
  <g id="Ojito">
    <rect x="190.37" y="288.55" width="192.7" height="91.76" fill="#606060" />
    <clipPath id="eyeClip">
      <ellipse class="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" />
    </clipPath>
    <ellipse class="outer-eye" cx="292.3" cy="335.43" rx="44.72" ry="30.01" fill="#3caa56" />
    <circle id="inner-eye" cx="291.69" cy="334.82" r="18.38" fill="#efefef" />
  </g>
</svg>

当我 post Chrome 错误跟踪器上的错误时,我会编辑我的问题和答案。

编辑:Chromium bug reported

编辑 2:对于另一个很好的解决方法,请查看

在这种情况下,最好使用剪辑路径或遮罩,因为您有更多元素需要 animated/masked 关闭。在此示例中,我选择了 CSS 剪辑路径,因为您从 CSS 中的动画开始。

我的示例在 Chrome 97 中运行良好。

另一种选择是使用 SVG animation with SMIL。我希望它也能在 Chrome 中工作。在某些情况下,它比 CSS.

中的掩码或剪辑路径更灵活

我使用 SvgPathEditor 构建路径。

@keyframes eye-blink {
  0%,
  100% {
    clip-path: path('M 3 5 C 6 6 9 7 13 5 C 9 2 6 3 3 5');
  }
  50% {
    clip-path: path('M 3 5 C 6 5 9 5 13 5 C 9 5 6 5 3 5');
  }
}

#Ojito g {
  clip-path: path('M 3 5 C 6 6 9 7 13 5 C 9 2 6 3 3 5');
  animation: eye-blink 4s ease infinite;
}
<svg id="composicion" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 10" width="400">
  <g id="Ojito">
    <rect width="16" height="10" fill="#606060" />
    <g>
      <rect width="16" height="10" fill="white" />
      <circle id="inner-eye" cx="8" cy="4.8" r="2" fill="#333" />
      <circle id="inner-eye" cx="8" cy="4.8" r="1.2" fill="black" />
    </g>
  </g>
</svg>