CSS3关键帧动画的“时间线”问题

CSS3 Keyframe Animation issue with "timelines"

本文关键字:时间线 问题 关键帧 动画 CSS3      更新时间:2023-09-26

在下面的例子中,我有3个div,他们需要使用CSS3关键帧动画动画与以下规则(当我提到隐藏/显示在下面的文本实际上使用不透明度0.1/1的CSS):

A)当页面加载 时
  • 显示ladyDefault
  • ladyCorrect是隐藏的
  • ladyWrong是隐藏的

B)当用户点击btnCorrect

  • ladyDefault是隐藏的
  • 显示ladyCorrect
  • ladyWrong是隐藏的

C)当用户点击btnWrong

  • ladyDefault是隐藏的
  • ladyCorrect是隐藏的
  • 显示ladyWrong
目前:

  • 序列情况A)和B)工作正常

  • 序列情况A)和C)工作正常

但我无法修复以下情况:

  • 序列情况A)和B)和C)不工作(ladyWrong未显示)。

  • 序列情况A)和C)和B)不工作(ladyCorrect未显示)。

我想知道如何修复它可能只使用CSS 3.

仅使用Google Chrome测试以下示例。

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyWrong.classList.add('hideLadyWrong');
    ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyCorrect.classList.add('hideLadyCorrect');
    ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
    width: 100px;
    height: 150px;
    display: inline-block;
    margin: 5px;
}
#ladyDefault {
    background-color: blue;
}
#ladyCorrect {
    background-color: green;
    opacity: 0.1;
}
#ladyWrong {
    background-color: red;
    opacity: 0.1;
}
#btnCorrect,
#btnWrong {
    height: 50px;
    width: 100px;
    display: inline-block;
    margin: 5px;
}
#btnCorrect {
    background-color: lime;
}
#btnWrong {
    background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyDefault {
    animation-name: hideLadyDefault;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}
.showLadyCorrect {
    animation-name: showLadyCorrect;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
@keyframes hideLadyCorrect {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyCorrect {
    animation-name: hideLadyCorrect;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both
    animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}
.showLadyWrong {
    animation-name: showLadyWrong;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
@keyframes hideLadyWrong {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyWrong {
    animation-name: hideLadyWrong;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both;
    animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>

原始答:

在添加新类之前,还需要删除以前的类。当你在添加一个新类之前没有删除其他类时,它们中的每一个都试图在同一个元素上设置一个animation,就像CSS中经常出现的情况一样,选择器(类)在CSS中稍后定义。

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
  ladyDefault.classList.add('hideLadyDefault');
  ladyWrong.classList.remove('showLadyWrong');
  ladyWrong.classList.add('hideLadyWrong');
  ladyCorrect.classList.remove('hideLadyCorrect');
  ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
  ladyDefault.classList.add('hideLadyDefault');
  ladyCorrect.classList.remove('showLadyCorrect');
  ladyCorrect.classList.add('hideLadyCorrect');
  ladyWrong.classList.remove('hideLadyWrong');
  ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
  width: 100px;
  height: 150px;
  display: inline-block;
  margin: 5px;
}
#ladyDefault {
  background-color: blue;
}
#ladyCorrect {
  background-color: green;
  opacity: 0.1;
}
#ladyWrong {
  background-color: red;
  opacity: 0.1;
}
#btnCorrect,
#btnWrong {
  height: 50px;
  width: 100px;
  display: inline-block;
  margin: 5px;
}
#btnCorrect {
  background-color: lime;
}
#btnWrong {
  background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0.1;
  }
}
.hideLadyDefault {
  animation-name: hideLadyDefault;
  animation-duration: 0;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
  0% {
    opacity: 0.1;
  }
  100% {
    opacity: 1;
  }
}
.showLadyCorrect {
  animation-name: showLadyCorrect;
  animation-duration: 1s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
@keyframes hideLadyCorrect {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0.1;
  }
}
.hideLadyCorrect {
  animation-name: hideLadyCorrect;
  animation-duration: 0;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: both animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
  0% {
    opacity: 0.1;
  }
  100% {
    opacity: 1;
  }
}
.showLadyWrong {
  animation-name: showLadyWrong;
  animation-duration: 1s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
@keyframes hideLadyWrong {
  0% {
    opacity: 1;
  }
  100% {
    opacity: 0.1;
  }
}
.hideLadyWrong {
  animation-name: hideLadyWrong;
  animation-duration: 0;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: both;
  animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>


只有一个关键帧规则的解决方案:

您也可以使用单个@keyframes规则而不是使用多个规则来达到相同的效果。所需要做的就是将hideanimation-direction设置为reverse。但是旧的类仍然必须被删除,因为一旦在元素上设置了动画,UA就会记住我在这个答案中提到的它的执行。

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
  ladyDefault.classList.add('hideLadyDefault');
  ladyWrong.classList.remove('showLadyWrong');
  ladyWrong.classList.add('hideLadyWrong');
  ladyCorrect.classList.remove('hideLadyCorrect');
  ladyCorrect.classList.add('showLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
  ladyDefault.classList.add('hideLadyDefault');
  ladyCorrect.classList.remove('showLadyCorrect');
  ladyCorrect.classList.add('hideLadyCorrect');
  ladyWrong.classList.remove('hideLadyWrong');
  ladyWrong.classList.add('showLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
  width: 100px;
  height: 150px;
  display: inline-block;
  margin: 5px;
}
#ladyDefault {
  background-color: blue;
}
#ladyCorrect {
  background-color: green;
  opacity: 0.1;
}
#ladyWrong {
  background-color: red;
  opacity: 0.1;
}
#btnCorrect,
#btnWrong {
  height: 50px;
  width: 100px;
  display: inline-block;
  margin: 5px;
}
#btnCorrect {
  background-color: lime;
}
#btnWrong {
  background-color: darkred;
}
/*
--------------------------- lady default
*/
.hideLadyDefault {
  animation-name: show;
  animation-duration: 0;
  animation-iteration-count: 1;
  animation-direction: reverse;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes show {
  0% {
    opacity: 0.1;
  }
  100% {
    opacity: 1;
  }
}
.showLadyCorrect {
  animation-name: show;
  animation-duration: 1s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
.hideLadyCorrect {
  animation-direction: reverse;
}
/*
--------------------------- lady wrong
*/
.showLadyWrong {
  animation-name: show;
  animation-duration: 1s;
  animation-iteration-count: 1;
  animation-direction: normal;
  animation-fill-mode: forwards;
  animation-delay: 0;
}
.hideLadyWrong {
  animation-direction: reverse;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>


带转换的解决方案:(可能更合适)

如果可以的话,最好使用transition而不是animation。在这里,您可以通过内联样式属性设置opacity,并让transition属性处理其余的内容。与动画不同,缺省情况下,转换可以执行反向状态。(这是最好的选择,如果它只是一个简单的不透明度从0.1到1的变化,如果它是一个复杂的多步骤的变化,过渡是超出范围的。)

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
  ladyDefault.style["opacity"] = "0.1";
  ladyWrong.style["opacity"] = "0.1";
  ladyCorrect.style["opacity"] = "1";
});
btnWrong.addEventListener('click', function(event) {
  ladyDefault.style["opacity"] = "0.1";
  ladyCorrect.style["opacity"] = "0.1";
  ladyWrong.style["opacity"] = "1";
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
  width: 100px;
  height: 150px;
  display: inline-block;
  margin: 5px;
}
#ladyDefault {
  background-color: blue;
  transition: all 1s ease;
}
#ladyCorrect {
  background-color: green;
  opacity: 0.1;
  transition: all 1s ease;
}
#ladyWrong {
  background-color: red;
  opacity: 0.1;
  transition: all 1s ease;
}
#btnCorrect,
#btnWrong {
  height: 50px;
  width: 100px;
  display: inline-block;
  margin: 5px;
}
#btnCorrect {
  background-color: lime;
}
#btnWrong {
  background-color: darkred;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>

您正确添加了所有类,但您没有稍后删除添加的类,这就是问题所在。将侦听器更改为

btnCorrect.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyWrong.classList.add('hideLadyWrong');
    ladyCorrect.classList.add('showLadyCorrect');
    ladyCorrect.classList.remove('hideLadyCorrect'); //added
});
btnWrong.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyCorrect.classList.add('hideLadyCorrect');
    ladyWrong.classList.add('showLadyWrong');
    ladyWrong.classList.remove('hideLadyWrong'); //added
});

var btnCorrect = document.getElementById('btnCorrect');
var btnWrong = document.getElementById('btnWrong');
var ladyDefault = document.getElementById('ladyDefault');
var ladyCorrect = document.getElementById('ladyCorrect');
var ladyWrong = document.getElementById('ladyWrong');
btnCorrect.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyWrong.classList.add('hideLadyWrong');
    ladyCorrect.classList.add('showLadyCorrect');
    ladyCorrect.classList.remove('hideLadyCorrect');
});
btnWrong.addEventListener('click', function(event) {
    ladyDefault.classList.add('hideLadyDefault');
    ladyCorrect.classList.add('hideLadyCorrect');
    ladyWrong.classList.add('showLadyWrong');
    ladyWrong.classList.remove('hideLadyWrong');
});
#ladyDefault,
#ladyCorrect,
#ladyWrong {
    width: 100px;
    height: 150px;
    display: inline-block;
    margin: 5px;
}
#ladyDefault {
    background-color: blue;
}
#ladyCorrect {
    background-color: green;
    opacity: 0.1;
}
#ladyWrong {
    background-color: red;
    opacity: 0.1;
}
#btnCorrect,
#btnWrong {
    height: 50px;
    width: 100px;
    display: inline-block;
    margin: 5px;
}
#btnCorrect {
    background-color: lime;
}
#btnWrong {
    background-color: darkred;
}
/*
--------------------------- lady default
*/
@keyframes hideLadyDefault {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyDefault {
    animation-name: hideLadyDefault;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
/*
--------------------------- lady correct
*/
@keyframes showLadyCorrect {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}
.showLadyCorrect {
    animation-name: showLadyCorrect;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
@keyframes hideLadyCorrect {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyCorrect {
    animation-name: hideLadyCorrect;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both
    animation-delay: 0;
}
/*
--------------------------- lady wrong
*/
@keyframes showLadyWrong {
    0% {
        opacity: 0.1;
    }
    100% {
        opacity: 1;
    }
}
.showLadyWrong {
    animation-name: showLadyWrong;
    animation-duration: 1s;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: forwards;
    animation-delay: 0;
}
@keyframes hideLadyWrong {
    0% {
        opacity: 1;
    }
    100% {
        opacity: 0.1;
    }
}
.hideLadyWrong {
    animation-name: hideLadyWrong;
    animation-duration: 0;
    animation-iteration-count: 1;
    animation-direction: normal;
    animation-fill-mode: both;
    animation-delay: 0;
}
<div id="ladyDefault">ladyDefault</div>
<div id="ladyCorrect">ladyCorrect</div>
<div id="ladyWrong">ladyWrong</div>
<div id="btnCorrect">btnCorrect</div>
<div id="btnWrong">btnWrong</div>