我有一个在 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 个关键帧,有没有办法将这些关键帧绑定到单击事件/按钮?
但是我想让动画与按钮按下相关联并根据每个按钮播放。当按下增加按钮时,我希望水位播放下一个关键帧,将水位带到下一个水位(相应地),反之亦然,当按下减少按钮时。
有人可以帮我解决这个问题吗?谢谢你。
您可以尝试的是将动画分成多个阶段,并根据按钮按下来播放每个阶段 - 按下按钮会改变一个全局变量,该变量本身用于选择要播放的动画阶段。以下内容并不完全正确,我不得不稍微修改一下 css 动画,但我认为它应该让您了解如何解决这个问题。
您无法使用 javascript 设置元素的伪属性,因此使用 CSS 自定义属性并将其分配给 DOM 元素的
:before
和 :after
状态 - 这些自定义 css 属性/变量可以使用 Javascript 轻松修改,这就是按钮的方式按可以修改播放的动画。
我考虑的另一个选择是使用各种 CSS 事件监听器 - 例如 animationend、animationcancel 和 animationstart 但我认为这增加了太多的复杂性
毫无疑问,您还可以使用其他几种方法 - 这就是我的方法...希望它有所帮助。
您应该能够修改各种 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>