我在2016年1月学习了CSS3 @keyframes
语法,两年后,我现在发现自己在我的工作中使用@keyframes
动画(比CSS3过渡更复杂,比基于javascript的动画)。
我真正想念的一件事是能够在几秒钟内表达@keyframes
而不是百分比。是否有任何黑客可以实现这一目标?
我知道我可以使用以下100s
黑客循环彩虹色,每3秒钟一个周期:
div {
width: 120px;
height: 120px;
background-color: violet;
animation: myAnimation 100s;
}
@keyframes myAnimation {
0% {background-color: red;}
3% {background-color: orange;}
6% {background-color: yellow;}
9% {background-color: green;}
12% {background-color: cyan;}
15% {background-color: blue;}
18% {background-color: violet;}
100% {background-color: violet;}
}

<div></div>
&#13;
但这意味着动画在(有效地)完成之后的另一个82秒仍在运行(虽然不知不觉)。除了其他问题之外,这使得多次迭代无法实现。
我真正想写的是:
@keyframes myAnimation {
0s {background-color: red;}
3s {background-color: orange;}
6s {background-color: yellow;}
9s {background-color: green;}
12s {background-color: cyan;}
15s {background-color: blue;}
18s {background-color: violet;}
}
有没有比我在上面的代码框中详述的方法更好的方法?
事后我意识到,上面的例子可能使上面的例子过于简单,因为它涉及动画单个元素,而我的问题最初是出于希望动画多个元素相互同步的动画。
所以,这是一个稍微详细的例子,显示的设置更接近于首先引起我问题的设置:
div {
display: inline-block;
width: 48px;
height: 48px;
margin-right: 6px;
}
div:nth-of-type(1) {
background-color: red;
}
div:nth-of-type(2) {
background-color: orange;
animation: myAnimationOrange 100s;
}
div:nth-of-type(3) {
background-color: yellow;
animation: myAnimationYellow 100s;
}
div:nth-of-type(4) {
background-color: green;
animation: myAnimationGreen 100s;
}
div:nth-of-type(5) {
background-color: cyan;
animation: myAnimationCyan 100s;
}
div:nth-of-type(6) {
background-color: violet;
animation: myAnimationViolet 100s;
}
@keyframes myAnimationOrange {
0% {background-color: white;}
1% {background-color: white;}
2% {background-color: orange;}
100% {background-color: orange;}
}
@keyframes myAnimationYellow {
0% {background-color: white;}
2% {background-color: white;}
3% {background-color: yellow;}
100% {background-color: yellow;}
}
@keyframes myAnimationGreen {
0% {background-color: white;}
3% {background-color: white;}
4% {background-color: green;}
100% {background-color: green;}
}
@keyframes myAnimationCyan {
0% {background-color: white;}
4% {background-color: white;}
5% {background-color: cyan;}
100% {background-color: cyan;}
}
@keyframes myAnimationViolet {
0% {background-color: white;}
5% {background-color: white;}
6% {background-color: violet;}
100% {background-color: violet;}
}
&#13;
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
&#13;
答案 0 :(得分:3)
不要忘记您可以在同一元素上运行多个动画,并且可以单独设置duration
,delay
和所有其他animation-...
规则。
例如,您可以将所有关键帧拆分为单键@keyframes规则 然后,当他们开始并将它们链接起来时,它很容易控制。
div {
width: 120px;
height: 120px;
background-color: violet;
animation-fill-mode: forwards;
animation-name: orange, yellow, green, cyan, blue, violet;
animation-delay: 0s, 3s, 6s, 9s, 12s, 15s, 18s;
animation-duration: 3s; /* same for all */
}
@keyframes orange {
to { background-color: orange; }
}
@keyframes yellow {
to { background-color: yellow; }
}
@keyframes green {
to { background-color: green; }
}
@keyframes cyan {
to { background-color: cyan; }
}
@keyframes blue {
to { background-color: blue; }
}
@keyframes violet {
to { background-color: violet; }
}
&#13;
<div></div>
&#13;
在这种情况下,您甚至不需要在同一元素上组合多个动画,只需相应地设置animation-delay
:
div {
/* same for all */
width: 60px;
height: 60px;
display: inline-block;
background-color: white;
animation-fill-mode: forwards;
animation-duration: 3s;
}
div:nth-of-type(1) {
animation-name: orange;
animation-delay: 0s;
}
div:nth-of-type(2) {
animation-name: yellow;
animation-delay: 3s;
}
div:nth-of-type(3) {
animation-name: green;
animation-delay: 6s;
}
div:nth-of-type(4) {
animation-name: cyan;
animation-delay: 9s;
}
div:nth-of-type(5) {
animation-name: blue;
animation-delay: 12s;
}
div:nth-of-type(6) {
animation-name: violet;
animation-delay: 15s;
}
@keyframes orange {
to { background-color: orange; }
}
@keyframes yellow {
to { background-color: yellow; }
}
@keyframes green {
to { background-color: green; }
}
@keyframes cyan {
to { background-color: cyan; }
}
@keyframes blue {
to { background-color: blue; }
}
@keyframes violet {
to { background-color: violet; }
}
&#13;
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
&#13;
但如果你想将两者结合在一起,那也很可能:
div {
/* same for all */
width: 60px;
height: 60px;
display: inline-block;
background-color: white;
animation-fill-mode: forwards;
animation-duration: 3s;
}
div:nth-of-type(1) {
animation-name: orange, yellow, green, cyan, blue, violet;
animation-delay: 0s, 3s, 6s, 9s, 12s, 15s;
}
div:nth-of-type(2) {
animation-name: yellow, green, cyan, blue, violet;
animation-delay: 3s, 6s, 9s, 12s, 15s;
}
div:nth-of-type(3) {
animation-name: green, cyan, blue, violet;
animation-delay: 6s, 9s, 12s, 15s;
}
div:nth-of-type(4) {
animation-name: cyan, blue, violet;
animation-delay: 9s, 12s, 15s;
}
div:nth-of-type(5) {
animation-name: blue, violet;
animation-delay: 12s, 15s;
}
div:nth-of-type(6) {
animation-name: violet;
animation-delay: 15s;
}
@keyframes orange {
to { background-color: orange; }
}
@keyframes yellow {
to { background-color: yellow; }
}
@keyframes green {
to { background-color: green; }
}
@keyframes cyan {
to { background-color: cyan; }
}
@keyframes blue {
to { background-color: blue; }
}
@keyframes violet {
to { background-color: violet; }
}
&#13;
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
&#13;
答案 1 :(得分:1)
目前不是。文档明确说明您只能使用百分比:
https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes
据推测,其背后的原因是动画的持续时间没有在关键帧中定义,而是在animation-duration
属性中定义,因此插值器必须能够将关键帧拉伸到任何持续时间。 / p>
答案 2 :(得分:1)
示例https://codepen.io/jakob-e/pen/vVXeOe
SCSS
body {
@include animation-timeline {
animation-iteration-count: infinite;
animation-fill-mode: forwards;
@include tween(0s, (background-color: violet));
@include tween(3s, (background-color: red));
@include tween(3s, (background-color: orange));
@include tween(3s, (background-color: yellow));
@include tween(3s, (background-color: green));
@include tween(3s, (background-color: cyan));
@include tween(3s, (background-color: blue));
@include tween(3s, (background-color: violet));
}
}
CSS输出
body {
animation-iteration-count: infinite;
animation-fill-mode: forwards;
animation-name: u33q65otn;
animation-duration: 21s;
}
@keyframes u33q65otn {
0% { background-color: violet; }
14.2857142857% { background-color: red; }
28.5714285714% { background-color: orange; }
42.8571428571% { background-color: yellow; }
57.1428571429% { background-color: green; }
71.4285714286% { background-color: cyan; }
85.7142857143% { background-color: blue; }
100% { background-color: violet; }
}
mixins
// global context flags using wierd ☠️ names to minimize
// chance of naming conflicts with other scss variables
$☠️--animation-timeline-duration: null;
$☠️--animation-timeline-tweens : null;
// mixin to create an animation context for nested tweens
// used to calculate the total duration of the animation
// converting each tween delay into percentages
@mixin animation-timeline($name: unique-id()) {
// global context flag to sum up duration
$☠️--animation-timeline-duration: 0s !global;
// global context map to hold animation tweens
$☠️--animation-timeline-tweens : () !global;
// mixin content (the included tweens)
@content;
// animation name and duration
// note! if no name is provided a unique id will be used
// this allows you to create one-time-use animations without
// having to deal with animation naming conflicts :-)
animation-name: $name;
animation-duration: $☠️--animation-timeline-duration;
// create keyframes
@keyframes #{$name} {
// loop through the included tweens
@each $time, $props in $☠️--animation-timeline-tweens {
// calculate percentage based on total duration
#{percentage($time/$☠️--animation-timeline-duration)}{
// print out the tween properties
@each $prop, $value in $props {
#{$prop}:$value;
}
}
}
}
// reset global context flags
$☠️--animation-timeline-duration: null !global;
$☠️--animation-timeline-tweens : null !global;
}
// mixin to create tweens based on a delay and a map
// containing the the tween properties*
//
// * using a map is not optimal – but for now you are not
// able to save @content to variables :(
//
@mixin tween($delay: 0s, $props: null){
// only do stuff if we are in a animation-timeline context
@if $☠️--animation-timeline-tweens {
// increment the total animation by the the tween delay
$☠️--animation-timeline-duration: $☠️--animation-timeline-duration + $delay !global;
// save current duration and tween props to the global tween map
$☠️--animation-timeline-tweens: map-merge($☠️--animation-timeline-tweens, ($☠️--animation-timeline-duration: $props)) !global;
}
}
答案 3 :(得分:-1)
你的黑客有点尴尬。为什么不直接使用18s
作为动画持续时间,并逐步循环显示百分比?
div {
width: 120px;
height: 120px;
background-color: violet;
animation: myAnimation 18s;
}
@keyframes myAnimation {
0% {background-color: red;}
18% {background-color: orange;}
37% {background-color: yellow;}
55% {background-color: green;}
71% {background-color: cyan;}
88% {background-color: blue;}
100% {background-color: violet;}
}
&#13;
<div></div>
&#13;
我不认为你应该能够在@keyframes
间隔内使用秒数。我们已经在CSS中使用其他所有内容的秒数。 See how it works here