如何让 CSS 关键帧在按下按钮时播放?

问题描述 投票:0回答:1

我有一个在 5 个关键帧中播放的 CSS 动画。但是,我想将这些关键帧绑定到一个按钮。

.water{
    width:162px;
    height: 162px;
    background-color: #1D89E7;
    border-radius: 50%;
    position: relative;
    overflow: hidden;
}
.water:before, .water:after{
    content:'';
    position: absolute;
    width:200%;
    height: 200%;
    top: -50%;
    left: 50%;
    background: #fff;
}
.water:before{
    border-radius: 45%;
    background:#fff;
    animation:wave 10s linear infinite;
}
.water:after{
    border-radius: 35%;
    background:rgba(255, 255, 255, 0.3);
    animation:wave 10s linear infinite;
}

@keyframes wave{
    0%{
        transform: translate(-50%, -50%) rotate(0);
        top: -30%;
    }
    25%{
        top: -60%;
    }
    50%{
        transform: translate(-50%, -50%)  rotate(360deg);
        top: -90%;
    }

    75%{
        transform: translate(-50%, -50%)  rotate(360deg);
        top: -60%;
    }

    100%{
        transform: translate(-50%, -50%)  rotate(360deg);
        top: -30%;
    }
}
<div class="water"></div>
<button>Increase water by a level</button>
<button>Decrease water by a level</button>

https://codepen.io/Crispy-Pvper/pen/abPqpaY

现在动画的播放方式与正常动画一样,水位按预期上升然后下降。我有 5 个关键帧,有没有办法将这些关键帧绑定到单击事件/按钮?

但是我想让动画与按钮按下相关联并根据每个按钮播放。当按下增加按钮时,我希望水位播放下一个关键帧,将水位带到下一个水位(相应地),反之亦然,当按下减少按钮时。

有人可以帮我解决这个问题吗?谢谢你。

html css css-selectors css-animations css-transitions
1个回答
0
投票

您可以尝试的是将动画分成多个阶段,并根据按钮按下来播放每个阶段 - 按下按钮会改变一个全局变量,该变量本身用于选择要播放的动画阶段。以下内容并不完全正确,我不得不稍微修改一下 css 动画,但我认为它应该让您了解如何解决这个问题。

您无法使用 javascript 设置元素的伪属性,因此使用 CSS 自定义属性并将其分配给 DOM 元素的

:before
:after
状态 - 这些自定义 css 属性/变量可以使用 Javascript 轻松修改,这就是按钮的方式按可以修改播放的动画。

我考虑的另一个选择是使用各种 CSS 事件监听器 - 例如 animationendanimationcancelanimationstart 但我认为这增加了太多的复杂性

毫无疑问,您还可以使用其他几种方法 - 这就是我的方法...希望它有所帮助。

您应该能够修改各种 css 动画阶段以适合您的预期愿景 - 我不确定动画反转是否正确,但它很接近?!

let i = 0; //   to help calculate where in animation we are
const stages = 5; //    number of distinct stages in animation


let style = document.documentElement.style;
style.setProperty('--anim-stages', stages);

document.addEventListener('click', e => {
  if (e.target instanceof HTMLButtonElement && e.target.dataset.dir != null) {

    switch (e.target.dataset.dir) {
      case 'forward':
        if (i < (stages - 1)) i++;
        else return false;
        break;
      case 'reverse':
        if (i > 0) i--;
        else return false;
        break;
    }

    style.setProperty('--anim-direction', e.target.dataset.dir);
    style.setProperty('--anim-name', `wave${i}`);
    style.setProperty('--anim-playstate', 'running');

    console.clear();
    console.log(style.getPropertyValue('--anim-name'))
  }
});
:root {
  --anim-duration: 10s;
  --anim-timing: linear;
  --anim-playstate: paused;
  --anim-name: null;
  --anim-direction: forward;
  --anim-fillmode: both;
  --anim-stages: 1;
}

.water {
  width: 162px;
  height: 162px;
  background-color: #1D89E7;
  border-radius: 50%;
  position: relative;
  overflow: hidden;
  margin: 1rem auto;
  float: none;
}

section {
  display: flex;
  flex-direction: row;
  justify-content: space-around;
}

button {
  margin: 0.25rem auto;
  padding: 1rem;
}

.water:before,
.water:after {
  content: '';
  position: absolute;
  width: 200%;
  height: 200%;
  top: -50%;
  left: 50%;
  background: #fff;
  animation-fill-mode: var(--anim-fillmode);
  animation-direction: var(--anim-direction);
  animation-play-state: var(--anim-playstate);
  animation-timing-function: var(--anim-timing);
  animation-duration: calc( var(--anim-duration) / var(--anim-stages));
}

.water:before {
  border-radius: 45%;
  background: #fff;
  animation-name: var(--anim-name);
}

.water:after {
  border-radius: 35%;
  background: rgba(255, 255, 255, 0.3);
  animation-name: var(--anim-name);
}

@keyframes null {
  from {
    transform: translate(-50%, -50%) rotate(0);
    top: -30%;
  }
  to {
    transform: translate(-50%, -50%) rotate(0);
    top: -30%;
  }
}
@keyframes wave0 {
  from {
    transform: translate(-50%, -50%) rotate(360deg);
    top: -30%;
  }
  to {
    transform: translate(-50%, -50%) rotate(90deg);
    top: -60%;
  }
}
@keyframes wave1 {
  from {
    transform: translate(-50%, -50%) rotate(360deg);
    top: -30%;
  }
  to {
    transform: translate(-50%, -50%) rotate(90deg);
    top: -60%;
  }
}

@keyframes wave2 {
  from {
    transform: translate(-50%, -50%) rotate(180deg);
    top: -60%;
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
    top: -90%;
  }
}

@keyframes wave3 {
  from {
    transform: translate(-50%, -50%) rotate(180deg);
    top: -90%;
  }
  to {
    transform: translate(-50%, -50%) rotate(360deg);
    top: -60%;
  }
}

@keyframes wave4 {
  from {
    transform: translate(-50%, -50%) rotate(360deg);
    top: -60%;
  }
  to {
    transform: translate(-50%, -50%) rotate(90deg);
    top: -30%;
  }
}
<div class="water"></div>
<section>
  <button data-dir='forward'>Increase water by a level</button>
  <button data-dir='reverse'>Decrease water by a level</button>
</section>

© www.soinside.com 2019 - 2024. All rights reserved.