为什么我的 div 的背景颜色在 CSS 动画开始时会改变?



>目标

我想为div设置动画,以便:

  • 在 10 秒的跨度内,width从 100% 变为 0%。
  • 经过 5 秒后,background-color应从绿色变为橙色。
  • 经过 7.5 秒后,background-color应从橙色变为红色。
  • 编辑:我希望颜色过渡发生在2秒的时间内。

问题

当我开始动画时,div的颜色会立即变为橙色。更改不是动画,颜色只是从 100% 绿色变为 100% 橙色。

这些要求正在发挥作用

  • 宽度动画工作正常。
  • 在 7.5 秒时,orange-to-red动画正常工作。

笔记

  • 我通过将类timer-animation添加到div#timerBar来启动动画。我不确定这是否是启动动画的首选方式。

  • 在 5 秒时,animationstart事件触发green-to-orange(如编码),但div不会改变颜色,因为它已经是橙色。

  • 我是CSS动画的新手,但我已经编码了30年。

let timerBar = document.getElementById('timerBar');
let animationNameList = document.getElementById('animation-names');
const startAnimation = function() {
timerBar.classList.remove('pause');
timerBar.classList.toggle('timer-animation');
animationNameList.replaceChildren();
};
const pauseAnimation = function() {
timerBar.classList.toggle('pause');
};
timerBar.addEventListener('animationstart', (e) => {
let li = document.createElement('li');
li.innerText = e.animationName;
animationNameList.appendChild(li);        
});
document
.getElementById('startButton')
.addEventListener('click',(startAnimation));
document
.getElementById('pauseButton')
.addEventListener('click',(pauseAnimation));
#timerBar {
background-color: #41b883;
height: 20px;
width: 100%;
}
.timer-animation {
animation-timing-function: linear;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-name: shrink-width,green-to-orange,orange-to-red;
animation-delay:0ms,5000ms,7500ms;
animation-duration:10000ms,2000ms,2000ms;
}
.pause {
animation-play-state: paused;
}
@keyframes shrink-width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes green-to-orange {
from {
background-color: #41b883;
}
to {
background-color: #ffa500;
}
}
@keyframes orange-to-red {
from {
background-color: #ffa500;
}
to {
background-color: #ff0000;
}
}
<div id="timerBar"></div>
<br/>
<button id="startButton">Start / Reset</button>
<button id="pauseButton">Pause</button>
<br />
<h4>When an animationstart event fires, its name will appear in this list.</h4>
<ul id="animation-names"></ul>

问题出在你的CSS代码上。如果我们看到CSS代码,我们可以看到您在同一类中使用了两个相同的动画关键帧green-to-orangeorange-to-red。尽管您设置了动画延迟,但它仍然会忽略green-to-orange动画,并从orange-to-red关键帧中获取初始颜色。因此,最好的选择是使用单个关键帧green-to-orange-to-red而不是两个单独的green-to-orangeorange-to-red关键帧。在单个动画green-to-orange-to-red中,您必须使用x%而不是fromto。你可以检查下面的代码,我已经更新了代码的CSS,我希望它能帮助你解决你的问题。

let timerBar = document.getElementById('timerBar');
let animationNameList = document.getElementById('animation-names');
const startAnimation = function() {
timerBar.classList.remove('pause');
timerBar.classList.toggle('timer-animation');
animationNameList.replaceChildren();
};
const pauseAnimation = function() {
timerBar.classList.toggle('pause');
};
timerBar.addEventListener('animationstart', (e) => {
let li = document.createElement('li');
li.innerText = e.animationName;
animationNameList.appendChild(li);        
});
document
.getElementById('startButton')
.addEventListener('click',(startAnimation));
document
.getElementById('pauseButton')
.addEventListener('click',(pauseAnimation));
#timerBar {
background-color: #41b883;
height: 20px;
width: 100%;
}
.timer-animation {
animation-timing-function: linear;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-name: shrink-width,green-to-orange-to-red;
animation-delay:0ms,0ms;
animation-duration:10000ms,10000ms;
}
.pause {
animation-play-state: paused;
}
@keyframes shrink-width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes green-to-orange-to-red {
0% {
background-color: #41b883;
}
50% {
background-color: #ffa500;
}
100% {
background-color: #ff0000;
}
}
<div id="timerBar"></div>
<br/>
<button id="startButton">Start / Reset</button>
<button id="pauseButton">Pause</button>
<br />
<h4>When an animationstart event fires, its name will appear in this list.</h4>
<ul id="animation-names"></ul>

您不需要使用多个动画关键帧。使用单个关键帧。在 0% 时,它将变为绿色,在 50% 时,它将逐渐从绿色变为橙色,在 75% 时,它将从橙色变为红色,并将保持红色直到 100%。

您无需使用动画延迟,也无需为两个关键帧设置动画持续时间 10000 毫秒。

let timerBar = document.getElementById('timerBar');
let animationNameList = document.getElementById('animation-names');
const startAnimation = function() {
timerBar.classList.remove('pause');
timerBar.classList.toggle('timer-animation');
animationNameList.replaceChildren();
};
const pauseAnimation = function() {
timerBar.classList.toggle('pause');
};
timerBar.addEventListener('animationstart', (e) => {
let li = document.createElement('li');
li.innerText = e.animationName;
animationNameList.appendChild(li);        
});
document
.getElementById('startButton')
.addEventListener('click',(startAnimation));
document
.getElementById('pauseButton')
.addEventListener('click',(pauseAnimation));
#timerBar {
background-color: #41b883;
height: 20px;
width: 100%;
}
.timer-animation {
animation-timing-function: linear;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-name: shrink-width, green-to-orange-to-red;
animation-duration:10000ms, 10000ms;
}
.pause {
animation-play-state: paused;
}
@keyframes shrink-width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes green-to-orange-to-red {
0%{
background-color: #41b883;
}
50%{
background-color: #ffa500;
}
75%{
background-color: #ff0000;
}
100%{
background-color: #ff0000;
}
}
<div id="timerBar"></div>
<br/>
<button id="startButton">Start / Reset</button>
<button id="pauseButton">Pause</button>
<br />
<h4>When an animationstart event fires, its name will appear in this list.</h4>
<ul id="animation-names"></ul>

感谢大家的建议。他们很有帮助,但不太符合我的要求。我希望颜色过渡的周期仅为 2 秒,而不是在整个 10 秒的动画中淡入淡出。

我最终在动画和过渡的黑客组合中解决了这个问题。

  1. 我创建了一个名为_dummy_的动画关键帧,并在animationstart事件中观察它。
  2. 当这种情况发生时,我运行了一个方法来调整divclassList以将其切换到下一个颜色。
  3. 我在div中添加了transition: background-color 2000ms.

这三个变化一起使它能够满足我的要求。

我仍然不明白为什么我最初只使用动画的方法不起作用。我想阅读一些文档来准确解释为什么我的语法是错误的。

let timerBar = document.getElementById('timerBar');
let animationNames = document.getElementById('animation-names');
let colors = ['green','orange','red'];
let colorIndex = 0;
const getNextColor = function() {
let color = colors[colorIndex++];
if(colorIndex == colors.length)
colorIndex = 0;
return color;
};
const changeColor = function() {
colors.forEach(o=>timerBar.classList.remove(o));
timerBar.classList.add(getNextColor());
};
const startAnimation = function() {
colorIndex = 0;
changeColor();
timerBar.classList.remove('pause');
timerBar.classList.toggle('timer-animation');
animationNames.replaceChildren();
};
const pauseAnimation = function() {
timerBar.classList.toggle('pause');
};
timerBar.addEventListener('animationstart', (e) => {
if(e.animationName.includes('_dummy_')) {
changeColor();
}
let li = document.createElement('li');
li.innerText = e.animationName;
animationNames.appendChild(li);
});
document
.getElementById('startButton')
.addEventListener('click',(startAnimation));
document
.getElementById('pauseButton')
.addEventListener('click',(pauseAnimation));
#timerBar {
height: 20px;
width: 100%;
background-size: 0 50%;
transition: background-color 2000ms;
}
.green {
background-color: #41b883;
}
.orange {
background-color: #ffa500;
}
.red {
background-color: #ff0000;
}
.timer-animation {
animation-timing-function: linear;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: both;
animation-name: shrink-width, _dummy_, _dummy_;
animation-duration: 10000ms,0ms,0ms;
animation-delay: 0ms, 5000ms, 7500ms;
}
.pause {
animation-play-state: paused;
}
@keyframes shrink-width {
from {
width: 100%;
}
to {
width: 0%;
}
}
@keyframes _dummy_ {}
<div id="timerBar" class="green"></div>
<br/>
<button id="startButton">Start / Reset</button>
<button id="pauseButton">Pause</button>
<br />
<h4>When an animation starts, its name will appear in this list.</h4>
<ul id="animation-names"></ul>

最新更新