我正在使用CSS制作一个加载屏幕,希望它能具有物理上准确的行为。我尝试使用animation-timing-function: cubic-bezier(1, 0, 1, 1)
,看起来还不错,但不如我想象中真实。起初是因为我不知道参数的真正工作方式,我找到了这个网站,并随意尝试它们直到得到了令人满意的效果。
总之,我该如何在我的动画中添加物理上准确的行为呢? 我正在寻找一种仅使用CSS的解决方案,但如果不可能,JavaScript也可以。
以下是一个示例:
body{
background-color: #02a2bb;
}
.wrapper {
padding: 50px;
text-align: center;
}
.content {
height: 125px;
margin: 0 auto;
position: relative;
display: inline-block;
}
.ball {
width: 25px;
height: 25px;
display: inline-block;
border-radius: 50%;
bottom: 0;
position: relative;
background-color: #fff;
z-index: 1;
}
.ball-shadow {
width: 20px;
height: 6px;
border-radius: 50%;
position: absolute;
bottom: 9px;
left: 50%;
-webkit-transform: translateX(-50%);
-moz-transform: translateX(-50%);
transform: translateX(-50%);
}
.animated {
-webkit-animation-duration: 1s;
-moz-animation-duration: 1s;
-ms-animation-duration: 1s;
-o-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
-moz-animation-fill-mode: both;
-ms-animation-fill-mode: both;
-o-animation-fill-mode: both;
animation-fill-mode: both;
-webkit-animation-iteration-count: infinite;
-moz-animation-iteration-count: infinite;
-ms-animation-iteration-count: infinite;
-o-animation-iteration-count: infinite;
animation-iteration-count: infinite;
}
.animated.jump, .animated.displace, .animated.diffuse-scale {
-webkit-animation-duration: 3s;
-moz-animation-duration: 3s;
-ms-animation-duration: 3s;
-o-animation-duration: 3s;
animation-duration: 3s;
}
@-webkit-keyframes jump {
0% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 0);
}
15% {
opacity: 1;
-webkit-transform: translate(0, 100px) scale(1.1, 0.9);
}
30% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 15px);
}
45% {
opacity: 1;
-webkit-transform: translate(0, 100px) scale(1.08, 0.92);
}
60% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 45px);
}
70% {
opacity: 1;
-webkit-transform: translate(0, 100px) scale(1.05, 0.95);
}
80% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 65px);
}
85% {
opacity: 1;
-webkit-transform: translate(0, 100px) scale(1.03, 0.97);
}
90% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 80px);
}
95% {
opacity: 1;
-webkit-transform: translate(0, 100px) scale(1.01, 0.99);
}
97% {
opacity: 1;
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: translate(0, 95px);
}
100% {
opacity: 0;
-webkit-transform: translate(0, 100px);
}
}
@keyframes jump {
0% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 0);
transform: translate(0, 0);
}
15% {
opacity: 1;
-moz-transform: translate(0, 100px) scale(1.1, 0.9);
transform: translate(0, 100px) scale(1.1, 0.9);
}
30% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 15px);
transform: translate(0, 15px);
}
45% {
opacity: 1;
-moz-transform: translate(0, 100px)scale(1.08, 0.92);
transform: translate(0, 100px)scale(1.08, 0.92);
}
60% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 45px);
transform: translate(0, 45px);
}
70% {
opacity: 1;
-moz-transform: translate(0, 100px)scale(1.05, 0.95);
transform: translate(0, 100px)scale(1.05, 0.95);
}
80% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 65px);
transform: translate(0, 65px);
}
85% {
opacity: 1;
-moz-transform: translate(0, 100px) scale(1.03, 0.97);
transform: translate(0, 100px) scale(1.03, 0.97);
}
90% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 80px);
transform: translate(0, 80px);
}
95% {
opacity: 1;
-moz-transform: translate(0, 100px) scale(1.01, 0.99);
transform: translate(0, 100px) scale(1.01, 0.99);
}
97% {
opacity: 1;
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: translate(0, 95px);
transform: translate(0, 95px);
}
100% {
opacity: 0;
-moz-transform: translate(0, 100px);
transform: translate(0, 100px);
}
}
@-webkit-keyframes diffuse-scale {
0% {
box-shadow: 0 14px 8px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.5, 1) translateX(-50%);
}
15% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%);
}
30% {
box-shadow: 0 14px 7px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.4, 1) translateX(-50%);
}
45% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%); }
60% {
box-shadow: 0 14px 5px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.3, 1) translateX(-50%); }
70% {
box-shadow: 0 14 2px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%);
}
80% {
box-shadow: 0 14px 4px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.2, 1) translateX(-50%);
}
85% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%);
}
90% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.1, 1) translateX(-50%);
}
95% {
box-shadow: 0 14px 3px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%);
}
97% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-animation-timing-function: cubic-bezier(1, 0, 1, 1);
-webkit-transform: scale(1.05, 1) translateX(-50%);
}
100% {
-webkit-transform: scale(1, 1) translateX(-50%);
}
}
@keyframes diffuse-scale {
0% {
box-shadow: 0 14px 8px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.5, 1) translateX(-50%);
transform: scale(1.5, 1) translateX(-50%);
}
15% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
30% {
box-shadow: 0 14px 7px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.4, 1) translateX(-50%);
transform: scale(1.4, 1) translateX(-50%);
}
45% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
60% {
box-shadow: 0 14px 5px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.3, 1) translateX(-50%);
transform: scale(1.3, 1) translateX(-50%);
}
70% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
80% {
box-shadow: 0 14px 4px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.2, 1) translateX(-50%);
transform: scale(1.2, 1) translateX(-50%);
}
85% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-webkit-transform: scale(1, 1) translateX(-50%);
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
90% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.1, 1) translateX(-50%);
transform: scale(1.1, 1) translateX(-50%);
}
95% {
box-shadow: 0 14px 3px rgba(0, 0, 0, 0.5);
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
97% {
box-shadow: 0 14px 2px rgba(0, 0, 0, 0.5);
-moz-animation-timing-function: cubic-bezier(1, 0, 1, 1);
animation-timing-function: cubic-bezier(1, 0, 1, 1);
-moz-transform: scale(1.05, 1) translateX(-50%);
transform: scale(1.05, 1) translateX(-50%);
}
100% {
-moz-transform: scale(1, 1) translateX(-50%);
transform: scale(1, 1) translateX(-50%);
}
}
@-webkit-keyframes displace {
from {
-webkit-animation-timing-function: linear;
-webkit-transform: translateX(0);
}
to {
-webkit-transform: translateX(100px);
}
}
@keyframes displace {
from {
-moz-animation-timing-function: linear;
animation-timing-function: linear;
-moz-transform: translateX(0);
transform: translateX(0);
}
to {
-moz-transform: translateX(100px);
transform: translateX(100px);
}
}
.jump {
-webkit-animation-name: jump;
-moz-animation-name: jump;
-ms-animation-name: jump;
-o-animation-name: jump;
animation-name: jump;
}
.diffuse-scale {
-webkit-animation-name: diffuse-scale;
-moz-animation-name: diffuse-scale;
-ms-animation-name: diffuse-scale;
-o-animation-name: diffuse-scale;
animation-name: diffuse-scale;
}
.displace {
-webkit-animation-name: displace;
-moz-animation-name: displace;
-ms-animation-name: displace;
-o-animation-name: displace;
animation-name: displace;
}
<div class="wrapper">
<div class="content animated infinite displace">
<span class="ball animated infinite jump"></span>
<span class="ball-shadow animated infinite diffuse-scale"></span>
</div>
</div>
建议
类似于less或SCSS的东西,有常数物理变量定义或者可以将值添加到函数中并模拟物理行为,甚至可能已经有模拟某些行为的mixin,我不知道是否有像样且只使用CSS的简单方法。