如何同步在不同时间启动/重新启动的 CSS 动画

2023-12-30

我正在尝试同步接收相同动画类的多个页面元素的 CSS 动画。

似乎有很多关于这个主题的帖子,但没有统一的解决方案,而且我找到的解决方案似乎都不适用于这种情况。

我在这里准备了一个jsfiddle来演示这个问题:

https://jsfiddle.net/gdf7szo5/1/ https://jsfiddle.net/gdf7szo5/1/

如果您单击任何字母,它将启动该字母的动画。如果您再次单击,它将切换到不同的动画,如果您第三次单击,它将把字母设置为根本没有动画。

期望的效果是一个动画中闪烁的所有字母彼此同步,并且另一动画中的任何字母彼此同步。需要明确的是,我并不是试图同步两个动画 - 我只是希望具有给定动画的所有元素彼此同步。

但目前,如果一个字母显示动画,而您将另一个字母设置为同一动画,除非您有绝对完美的时机,否则这两个字母的动画将不同步,即使它们是相同的动画。

这是正在运行的代码:

HTML:

<div>
  <span id="spA" onclick="toggleFx('spA')">A</span>
  <span id="spB" onclick="toggleFx('spB')">B</span>
  <span id="spC" onclick="toggleFx('spC')">C</span>
  <span id="spD" onclick="toggleFx('spD')">D</span>
</div>

CSS:

div {
  display: flex;
  flex-flow: column;
}

span {
  animation-name: pulse_active;
}

span.pulse {
    color: #f00;
    animation: pulse_active 1.5s ease-in infinite;
}

span.pulse_invert {
  color: #00f;
  animation: pulse_inverted 3s ease-in infinite;
}

@keyframes pulse_active {
    0% {
        opacity: 0;
    }
    50% {
        opacity: 0.66;
    }
    100% {
        opacity: 0;
    }
}

@keyframes pulse_inverted {
    0% {
        opacity: 1;
    }
    50% {
        opacity: 0.33;
    }
    100% {
        opacity: 1;
    }
}

JS:

let pulseNormal = {};
let pulseInvert = {};

function toggleFx(spanID) {

    let spanTarget = document.getElementById(spanID);
  
  // shift setting
  if (spanID in pulseInvert) {
  console.log('y');
  console.log(Object.keys(pulseInvert));
    delete pulseInvert[spanID]
  console.log(Object.keys(pulseInvert));
  } else if (spanID in pulseNormal) {
    pulseInvert[spanID] = true;
    delete pulseNormal[spanID];
  } else {
    pulseNormal[spanID] = true
  }
  
  // update display
  for (let sp of 'ABCD') {
    let span = document.getElementById(`sp${sp}`);
    
    // clear any prev animation
        span.classList.remove('pulse');     
    span.classList.remove('pulse_invert');
    
    // add/re-add animation as needed
    if (`sp${sp}` in pulseNormal) {             
        span.classList.add('pulse');
    } else if (`sp${sp}` in pulseInvert) {
        span.classList.add('pulse_invert');
    }
  }

}

以此目的document.getAnimations()是一个有用的方法。它返回当前有效的所有动画对象的数组,其目标元素是文档的后代。更多信息:https://developer.mozilla.org/en-US/docs/Web/API/Document/getAnimations https://developer.mozilla.org/en-US/docs/Web/API/Document/getAnimations

项目document.getAnimations()包括currentTime属性,可用于同步动画。更多信息:https://drafts.c​​sswg.org/web-animations/#dom-documentorshadowroot-getanimations https://drafts.csswg.org/web-animations/#dom-documentorshadowroot-getanimations

toggleFx函数被修改,现在它由三个部分组成。

第一部分,搜索document.getAnimations()并找到currentTime属性,其中animationName是其中之一pulse_active or pulse_inverted;然后将它们存储在相关变量中(即pulseActiveStart and pulseInvertedStart).

在第二部分中,className of spanTarget正如你所说的改变了。

在第三部分中,pulseActiveStart and pulseInvertedStart应用于currentTime相关动画的属性(与第一部分相反)。

function toggleFx(spanID) {

    let spanTarget = document.getElementById(spanID);
    
    let  pulseActiveStart;
    let  pulseInvertedStart;
    let anims = document.getAnimations()    
    for(let i = 0; i < anims.length; i++) { 
        if(anims[i].animationName == "pulse_active") pulseActiveStart = anims[i].currentTime;
        else if(anims[i].animationName == "pulse_inverted") pulseInvertedStart = anims[i].currentTime;      
    }
    
    
    
    if(spanTarget.classList.contains('pulse_invert')) {
        spanTarget.classList.remove('pulse_invert');    
        spanTarget.classList.remove('pulse');   
    } else if(spanTarget.classList.contains('pulse')) {
        spanTarget.classList.add('pulse_invert');   
        spanTarget.classList.remove('pulse');   
    } else {
        spanTarget.classList.add('pulse');  
    }
    
    anims = document.getAnimations()    
    for(let i = 0; i < anims.length; i++) { 
        if(anims[i].animationName == "pulse_active") {
            if(pulseActiveStart) anims[i].currentTime = pulseActiveStart;           
        } else if(anims[i].animationName == "pulse_inverted") {
            if(pulseInvertedStart) anims[i].currentTime = pulseInvertedStart;       
        }
    }
}
div {
  display: flex;
  flex-flow: column;
}

span.pulse {
    color: #f00;
    animation: pulse_active 1.5s ease-in infinite;
}

span.pulse_invert {
  color: #00f;
  animation: pulse_inverted 3s ease-in infinite;
}

@keyframes pulse_active {
    0% { opacity: 0; }
    50% { opacity: 0.66; }
    100% {  opacity: 0; }
}

@keyframes pulse_inverted {
    0% { opacity: 1; }
    50% { opacity: 0.33; }
    100% {  opacity: 1; }
}
<div>
  <span id="spA" onclick="toggleFx('spA')">A</span>
  <span id="spB" onclick="toggleFx('spB')">B</span>
  <span id="spC" onclick="toggleFx('spC')">C</span>
  <span id="spD" onclick="toggleFx('spD')">D</span>
</div>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何同步在不同时间启动/重新启动的 CSS 动画 的相关文章

随机推荐