将元素的 属性 强制为某个值,即使它正在动画中也是如此

Force a property of an element to a certain value even as it's being animated

我有两种类型的元素,我们称它们为 .a.b

它们可能设置了一些 CSS 动画。我无法控制这些关键帧,无法控制它们是否已设置,也无法控制它们的动画效果。

他们可能正在制作动画 opacity。但是,我希望我的 .a 元素上的 opacity 保持某个值,比方说 1,无论它是否是动画的。

考虑以下代码,其中我有三种情况:

  1. 我的元素上没有设置动画
  2. 有动画,但不是动画 opacity
  3. 有一个动画,opacity 是正在动画的属性之一

div {
  /* some dummy styles so we can see stuff */
  display: inline-block;
  width: 5em; height: 5em;
  background: purple;
}

[class*='ani'] { animation: a 1s ease-out infinite alternate }

.ani--one { animation-name: ani-one }

@keyframes ani-one { to { transform: scale(.5) } }

.ani--two { animation-name: ani-two }

@keyframes ani-two {
  to {
    opacity: 0;
    background: orange;
  }
}
<div class='a'></div>
<div class='b'></div>
<div class='a ani--one'></div>
<div class='b ani--one'></div>
<div class='a ani--two'></div>
<div class='b ani--two'></div>

在前两种情况下(1 = 没有关键帧动画和 2 = 关键帧动画,但它不是动画 opacity)我不需要做任何事情。

然而,在最后一种情况下,我需要以某种方式将 .a 元素的 opacity 强制为 1,取消 上的动画效果 属性.

我无法从 .a 元素中删除关键帧动画,因为我希望其他属性(在本例中为 background,一般情况下可能还有其他属性)继续存在动画。

我无法更改动画,因为我希望它按最初指定的方式工作,为其他元素 (.b) 设置 opacity 动画。

所以问题是,我如何检测 .a 元素上的 opacity 属性 是否正在动画,如果是,我如何强制它值保持在 1,而通过相同关键帧设置的其他属性正在设置动画?

我想使用 vanilla JS 解决这个问题,没有库。

您可以使用 !important

破解它
.solid-always { opacity:1 !important; }

然后将 at class 放在您不想改变其不透明度的位置。关键帧不应覆盖 !important.

现在突然想到我可以通过添加额外的 CSS 关键帧动画来做到这一点:

@keyframes opacity-override { 0%, 100% { opacity: 1 } }

现在,对于所有具有 animation 集的 .a 元素,我可以将 opacity-override 添加到动画名称中,它应该会处理这些事情!

此外,我可以用它来强制 opacity: 1 反对可能在悬停或添加其他 类 时设置的样式,这非常方便!

const _A = document.querySelectorAll('.a');

_A.forEach(a => {
  let aname = getComputedStyle(a).animationName;
  
  if(aname !== 'none') a.style.animationName = `${aname}, opacity-override`;
  else a.style.animation = 'opacity-override 1s infinite';
});
div {
  /* some dummy styles so we can see stuff */
  display: inline-block;
  width: 5rem; height: 5rem;
  background: purple;
  color: white;
  font: 700 3em/5rem verdana;
  text-align: center;
}

div:hover { opacity: .7 }

[class*='ani'] { animation: a 1s ease-out infinite alternate }

.ani--one { animation-name: ani-one }

@keyframes ani-one { to { transform: scale(.5) } }

.ani--two { animation-name: ani-two }

@keyframes ani-two {
  to {
    opacity: 0;
    background: orange;
  }
}

@keyframes opacity-override { 0%, 100% { opacity: 1 } }
<div class='a'>A</div>
<div class='b'>B</div>
<div class='a ani--one'>A</div>
<div class='b ani--one'>B</div>
<div class='a ani--two'>A</div>
<div class='b ani--two'>B</div>