将元素的属性强制为某个值,即使它正在被动画化

Posted

技术标签:

【中文标题】将元素的属性强制为某个值,即使它正在被动画化【英文标题】:Force a property of an element to a certain value even as it's being animated 【发布时间】:2017-09-12 06:21:50 【问题描述】:

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

他们可能设置了一些 CSS 动画。我无法控制这些关键帧、它们是否已设置以及它们正在制作的动画。

他们可能正在为opacity 制作动画。但是,我希望我的.a 元素上的opacity 保持一定的值,比如说1,不管它是否是动画的。

考虑下面的代码,我有三种情况:

    我的元素上没有设置动画 有动画,但没有动画opacity 有一个动画,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 解决这个问题,没有库。

【问题讨论】:

while(true)elem.opacity=1; 但那很 hacky... 【参考方案1】:

您可以使用 !important 破解它

.solid-always  opacity:1 !important; 

然后在课堂上放入你不希望其不透明度改变的那个。关键帧不应覆盖 !important。

【讨论】:

实际上,@keyframe 动画 do 会覆盖 !important,他们应该按照规范这样做。试试看吧。 抱歉,但按照规范,“重要作者声明”级联起源应该覆盖“动画声明”(w3.org/TR/css-cascade-4/#cascading),所以理论上,@Noobit 的回答基本上是正确的.问题是该规范多年来仅在 Firefox 中正确实施。但最近这个错误已在 Chromium (bugs.chromium.org/p/chromium/issues/detail?id=552085) 中得到修复【参考方案2】:

现在我突然想到,我可以通过添加额外的 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>

【讨论】:

以上是关于将元素的属性强制为某个值,即使它正在被动画化的主要内容,如果未能解决你的问题,请参考以下文章

Property Animation(属性动画)

jquery 动画

即使没有内容,如何强制 antd 选项卡全高(使用 React 和样式化组件)

片段之间动画的共享元素

XAML序列化 - 需要指定属性

强制删除文件,即使它正在被其他进程使用