在切换时反转多个 CSS 关键帧动画 [英] Reverse Multiple CSS Keyframe Animations On Toggle

查看:44
本文介绍了在切换时反转多个 CSS 关键帧动画的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作一个小动画,用于在深色和浅色模式之间切换我的网站.这是一个非常复杂的动画,所以我猜解决方案也会很复杂.

我基本上在类之间切换,但这会阻止我在切换按钮时反转动画.一直在网上寻找简单的解决方案,但没有找到任何解释如何使用多个 CSS 关键帧反转动画的方法.

这是代码的 CSS 部分,基本上重复了 8 次:

.line {宽度:1rem;高度:2rem;背景颜色:黑色;位置:绝对;显示:块;变换:translateY(5rem);边界半径:0.5em;}.is-dark {动画:is-dark 2s 向前;}@keyframes 是暗的 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(0) translateY(5rem);}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(0) translateY(5rem);}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0) translateY(0);}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(1rem) translateY(-1rem);}}

JS

let line = document.querySelector(.line");让 btn = document.querySelector(.btn");btn.addEventListener(点击",toggleDarkMode);功能切换暗模式(){line.classList.toggle("is-dark");}

这是此按钮的完整版本:https://jsfiddle.net/a6euokxy/4/

提前致谢,卢克·拉蒙

我有一些解决方案可以解决您的问题.我改进了 js 文件,确实添加到带有动画 alternate infinite paused; 属性的类中.在 html 中添加了带有动画的类.

工作示例LocalStorage

let theme = 'light';//获取所有容器元素const lines = document.querySelector('.container').querySelectorAll('div');让 btn = document.querySelector('.btn');btn.addEventListener('click', toggleDarkMode);功能切换暗模式(){如果(主题 === '光'){lines.forEach(line => {//删除不必要的 DOM 元素if (!line.hasAttribute('class')) 返回;//设置播放 2 秒动画后暂停setTimeout(() => {line.removeAttribute('style');}, 2000);//开始播放line.setAttribute('style', 'animation-play-state: running');});主题 = '黑暗';返回;}如果(主题 === '黑暗'){lines.forEach(line => {if (!line.hasAttribute('class')) 返回;setTimeout(() => {line.removeAttribute('style');}, 2000);line.setAttribute('style', 'animation-play-state: running');});主题 = '光';返回;}}

* {填充:0;边距:0;}.按钮 {显示:弹性;对齐内容:居中;边距顶部:3rem;}.button .btn {背景:无;边框:0.2rem纯黑色;字体大小:1rem;填充:1rem;边界半径:2rem;字体粗细:粗体;}.容器 {高度:100vh;显示:弹性;对齐内容:居中;对齐项目:居中;}#圆圈 {宽度:4rem;高度:4rem;边框:1rem纯黑色;边界半径:50%;位置:绝对;}#行{显示:弹性;对齐内容:居中;对齐项目:居中;}#lines1 {变换:旋转(45度);变换原点:中心;位置:绝对;显示:弹性;对齐内容:居中;对齐项目:居中;}.线,.line1,.line2,.line3,.line4,.line5,.line6,.line7 {宽度:1rem;高度:2rem;背景颜色:黑色;位置:绝对;显示:块;边界半径:0.5em;}.线 {变换:translateY(5rem);}.is-dark {动画:is-dark 2s 交替无限暂停;}@keyframes 是暗的 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(0) translateY(5rem);}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(0) translateY(5rem);}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0) translateY(0);}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(1rem) translateY(-1rem);}}.line1 {变换:translateY(-5rem);}.is-dark1 {动画:is-dark1 2s 交替无限暂停;}@关键帧是-dark1 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateY(-5rem);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateY(-5rem);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:0;}}.line2 {变换:translateX(5rem)旋转(90度);}.is-dark2 {动画:is-dark2 2s 交替无限暂停;}@keyframes is-dark2 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(5rem)旋转(90度);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(5rem)旋转(90度);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}}.line3 {变换:translateX(-5rem)旋转(90度);}.is-dark3 {动画:is-dark3 2s 交替无限暂停;}@keyframes is-dark3 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(-5rem)旋转(90度);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(-5rem)旋转(90度);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}}.line4 {变换:translateY(5rem);}.is-dark4 {动画:is-dark4 2s 交替无限暂停;}@关键帧是-dark4 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(0) translateY(5rem);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(0) translateY(5rem);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0) translateY(0);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(1rem) translateY(1rem);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(1rem) translateY(1rem);不透明度:0;}}.line5 {变换:translateY(-5rem);}.is-dark5 {动画:is-dark5 2s 交替无限暂停;}@keyframes is-dark5 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateY(-5rem);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateY(-5rem);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateY(0);不透明度:0;}}.line6 {变换:translateX(5rem)旋转(90度);}.is-dark6 {动画:is-dark6 2s 交替无限暂停;}@关键帧是-dark6 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(5rem)旋转(90度);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(5rem)旋转(90度);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}}.line7 {变换:translateX(-5rem)旋转(90度);}.is-dark7 {动画:is-dark7 2s 交替无限暂停;}@关键帧是-dark7 {0% {高度:2rem;宽度:1rem;边界半径:0.5em;变换:translateX(-5rem)旋转(90度);不透明度:100%;}33.33% {高度:1rem;宽度:1rem;边界半径:50%;变换:translateX(-5rem)旋转(90度);不透明度:100%;}66.66% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:100%;}66.67% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}100% {高度:3rem;宽度:3rem;边界半径:50%;变换:translateX(0)旋转(90度);不透明度:0;}}

<button class="btn">深色模式</button>

<div class="容器"><div id="圆圈"></div><div id="行"><div class="line is-dark"></div><div class="line1 is-dark1"></div><div class="line2 is-dark2"></div><div class="line3 is-dark3"></div>

<div id="lines1"><div class="line4 is-dark4"></div><div class="line5 is-dark5"></div><div class="line6 is-dark6"></div><div class="line7 is-dark7"></div>

I'm working on a little animation for toggling my website between dark- and light mode. It's a pretty complicated animation, so I'm guessing the solution will be complicated as well.

I basically toggle between classes, but this prevents me from being able to reverse the animation when toggling the button. Been looking for simple solutions around the web, but didn't find any that explains how to reverse the animation with multiple CSS keyframes.

Here's the CSS part of the code which is basically repeated 8 times:

.line {
width: 1rem;
height: 2rem;
background-color: black;
position: absolute;
display: block;
transform: translateY(5rem);
border-radius: 0.5em;
}
.is-dark {
animation: is-dark 2s forwards;
}
@keyframes is-dark {
    0% {
        height: 2rem;
        width: 1rem;
        border-radius: 0.5em;
        transform: translateX(0) translateY(5rem);
    }
    33.33% {
        height: 1rem;
        width: 1rem;
        border-radius: 50%;
        transform: translateX(0) translateY(5rem);
    }
    66.66% {
        height: 3rem;
        width: 3rem;
        border-radius: 50%;
        transform: translateX(0) translateY(0);
    }
    100% {
        height: 3rem;
        width: 3rem;
        border-radius: 50%;
        transform: translateX(1rem) translateY(-1rem);
    }
}

JS

let line = document.querySelector(".line");

let btn = document.querySelector(".btn");

btn.addEventListener("click", toggleDarkMode);

function toggleDarkMode() {
  line.classList.toggle("is-dark");
}

Here's the complete version of this button: https://jsfiddle.net/a6euokxy/4/

Thanks in advance, Luk Ramon

解决方案

I have some the solution for you issue. I improved js file, did add into classes with animation alternate infinite paused; properties. In html added classes with animation.

working example with LocalStorage

let theme = 'light';
// Get all container elements
const lines = document.querySelector('.container').querySelectorAll('div');

let btn = document.querySelector('.btn');

btn.addEventListener('click', toggleDarkMode);

function toggleDarkMode() {
  if (theme === 'light') {
    lines.forEach(line => {
      // Remove unnecessary DOM elements
      if (!line.hasAttribute('class')) return;
      // Set pause after play 2s animation
      setTimeout(() => {
        line.removeAttribute('style');
      }, 2000);
      // Start play
      line.setAttribute('style', 'animation-play-state: running');
    });
    theme = 'dark';
    return;
  }

  if (theme === 'dark') {
    lines.forEach(line => {
      if (!line.hasAttribute('class')) return;

      setTimeout(() => {
        line.removeAttribute('style');
      }, 2000);

      line.setAttribute('style', 'animation-play-state: running');
    });
    theme = 'light';
    return;
  }
}

* {
  padding: 0;
  margin: 0;
}

.button {
  display: flex;
  justify-content: center;
  margin-top: 3rem;
}

.button .btn {
  background: none;
  border: 0.2rem solid black;
  font-size: 1rem;
  padding: 1rem;
  border-radius: 2rem;
  font-weight: bold;
}

.container {
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

#circle {
  width: 4rem;
  height: 4rem;
  border: 1rem solid black;
  border-radius: 50%;
  position: absolute;
}

#lines {
  display: flex;
  justify-content: center;
  align-items: center;
}

#lines1 {
  transform: rotate(45deg);
  transform-origin: center;
  position: absolute;
  display: flex;
  justify-content: center;
  align-items: center;
}

.line,
.line1,
.line2,
.line3,
.line4,
.line5,
.line6,
.line7 {
  width: 1rem;
  height: 2rem;
  background-color: black;
  position: absolute;
  display: block;
  border-radius: 0.5em;
}

.line {
  transform: translateY(5rem);
}

.is-dark {
  animation: is-dark 2s alternate infinite paused;
}

@keyframes is-dark {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(0) translateY(5rem);
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(0) translateY(5rem);
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) translateY(0);
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(1rem) translateY(-1rem);
  }
}

.line1 {
  transform: translateY(-5rem);
}

.is-dark1 {
  animation: is-dark1 2s alternate infinite paused;
}

@keyframes is-dark1 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateY(-5rem);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateY(-5rem);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 0;
  }
}

.line2 {
  transform: translateX(5rem) rotate(90deg);
}

.is-dark2 {
  animation: is-dark2 2s alternate infinite paused;
}

@keyframes is-dark2 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(5rem) rotate(90deg);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(5rem) rotate(90deg);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
}

.line3 {
  transform: translateX(-5rem) rotate(90deg);
}

.is-dark3 {
  animation: is-dark3 2s alternate infinite paused;
}

@keyframes is-dark3 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(-5rem) rotate(90deg);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(-5rem) rotate(90deg);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
}

.line4 {
  transform: translateY(5rem);
}

.is-dark4 {
  animation: is-dark4 2s alternate infinite paused;
}

@keyframes is-dark4 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(0) translateY(5rem);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(0) translateY(5rem);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) translateY(0);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(1rem) translateY(1rem);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(1rem) translateY(1rem);
    opacity: 0;
  }
}

.line5 {
  transform: translateY(-5rem);
}

.is-dark5 {
  animation: is-dark5 2s alternate infinite paused;
}

@keyframes is-dark5 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateY(-5rem);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateY(-5rem);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateY(0);
    opacity: 0;
  }
}

.line6 {
  transform: translateX(5rem) rotate(90deg);
}

.is-dark6 {
  animation: is-dark6 2s alternate infinite paused;
}

@keyframes is-dark6 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(5rem) rotate(90deg);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(5rem) rotate(90deg);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
}

.line7 {
  transform: translateX(-5rem) rotate(90deg);
}

.is-dark7 {
  animation: is-dark7 2s alternate infinite paused;
}

@keyframes is-dark7 {
  0% {
    height: 2rem;
    width: 1rem;
    border-radius: 0.5em;
    transform: translateX(-5rem) rotate(90deg);
    opacity: 100%;
  }
  33.33% {
    height: 1rem;
    width: 1rem;
    border-radius: 50%;
    transform: translateX(-5rem) rotate(90deg);
    opacity: 100%;
  }
  66.66% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 100%;
  }
  66.67% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
  100% {
    height: 3rem;
    width: 3rem;
    border-radius: 50%;
    transform: translateX(0) rotate(90deg);
    opacity: 0;
  }
}

<div class="button">
  <button class="btn">Dark Mode</button>
</div>
<div class="container">
  <div id="circle"></div>
  <div id="lines">
    <div class="line is-dark"></div>
    <div class="line1 is-dark1"></div>
    <div class="line2 is-dark2"></div>
    <div class="line3 is-dark3"></div>
  </div>
  <div id="lines1">
    <div class="line4 is-dark4"></div>
    <div class="line5 is-dark5"></div>
    <div class="line6 is-dark6"></div>
    <div class="line7 is-dark7"></div>
  </div>
</div>

这篇关于在切换时反转多个 CSS 关键帧动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆