调整 CSS 微调器动画以完成而不是重复
Adapt CSS Spinner Animation to Finish instead of Repeat
我正在尝试创建如下所示的相同动画:
body {
text-align: center;
background: #222;
}
svg {
position: absolute;
display: block;
}
.container {
display: inline-block;
position: relative;
width: 50px;
}
.container #Layer_2 {
width: 60px;
stroke-dasharray: 121;
stroke-dashoffset: 121;
transform: rotate(270deg);
}
.container #Layer_2.on {
animation: circle 1.4s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@keyframes circle {
0% {
stroke-dashoffset: 121;
transform: rotate(90deg);
}
100% {
stroke-dashoffset: 0;
}
}
<div class="container">
<svg id="Layer_2" class="on" viewBox="0 0 50 50">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #ddd;
stroke-miterlimit: 10;
stroke-width: 1px;
}
</style>
</defs>
<circle class="cls-1" cx="25" cy="25" r="19.27" />
</svg>
</div>
但是,理想情况下我不想使用 SVG。我的网站上已经有一个使用类似动画的微调器:
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
font-family: "Avenir Next", sans-serif;
margin: 0;
outline: none;
padding: 0;
}
.spinner-wrapper {
display: inline-block;
position: relative;
width: 64px;
height: 64px;
animation: wrapper-rotate 1568ms linear infinite;
--spinner-border-width: 3px;
--spinner-color: black;
}
.spinner-wrapper .spinner {
position: absolute;
width: 100%;
height: 100%;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper {
display: block;
position: relative;
width: 50%;
height: 100%;
float: left;
overflow: hidden;
}
.spinner-wrapper .circle-clipper.circle-clipper-left .circle {
left: 0;
border-right-color: transparent !important;
transform: rotate(129deg);
animation: left-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper.circle-clipper-right .circle {
right: 0;
border-left-color: transparent !important;
transform: rotate(-129deg);
animation: right-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper .circle {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 200%;
height: 100%;
border: var(--spinner-border-width) solid var(--spinner-color);
border-bottom-color: transparent !important;
border-radius: 50%;
}
.spinner-wrapper .gap-patch {
position: absolute;
top: 0;
left: 45%;
width: 10%;
height: 100%;
overflow: hidden;
}
.spinner-wrapper .gap-patch .circle {
width: 1000%;
left: -450%;
}
@keyframes wrapper-rotate {
to {
transform: rotate(360deg);
}
}
@keyframes fill-unfill-rotate {
12.5% {
transform: rotate(135deg);
}
25% {
transform: rotate(270deg);
}
37.5% {
transform: rotate(405deg);
}
50% {
transform: rotate(540deg);
}
62.5% {
transform: rotate(675deg);
}
75% {
transform: rotate(810deg);
}
87.5% {
transform: rotate(945deg);
}
to {
transform: rotate(1080deg);
}
}
@keyframes left-spin {
from {
transform: rotate(130deg);
}
50% {
transform: rotate(-5deg);
}
to {
transform: rotate(130deg);
}
}
@keyframes right-spin {
from {
transform: rotate(-130deg);
}
50% {
transform: rotate(5deg);
}
to {
transform: rotate(-130deg);
}
}
<div class="spinner-wrapper">
<div class="spinner">
<div class="circle-clipper circle-clipper-left">
<div class="circle"></div>
</div>
<div class="gap-patch circle-clipper">
<div class="circle"></div>
</div>
<div class="circle-clipper circle-clipper-right">
<div class="circle"></div>
</div>
</div>
</div>
上面的动画与我想要实现的类似,但显然它是无限的,并没有完全完成整个圆圈。
任何人都可以建议我可以对我现有的解决方案做些什么,以使其适应第一个动画吗?
我尝试了各种方法,但没有取得任何真正的进展。
我会考虑使用 clip-path
的想法,就像我在 this previous answer:
中所做的那样
.loader {
width:150px;
height:150px;
display:inline-block;
margin:20px;
border:2px solid #fff;
border-radius:50%;
transform:scaleX(var(--s,1)) rotate(225deg);
clip-path:polygon(50% 50%,0 0,0 0,0 0, 0 0,0 0);
animation:change 1.4s linear forwards;
}
.opp {
--s:-1;
}
@keyframes change {
25% {
clip-path:polygon(50% 50%,0 0, 0 100%,0 100%,0 100%,0 100%);
}
50% {
clip-path:polygon(50% 50%,0 0,0 100%, 100% 100%, 100% 100%,100% 100%);
}
75% {
clip-path:polygon(50% 50%,0 0,0 100%,100% 100%, 100% 0,100% 0);
}
100% {
clip-path:polygon(50% 50%,0 0,0 100%,100% 100%, 100% 0, 0% 0%);
transform:scaleX(var(--s,1)) rotate(45deg);
}
}
body {
background:black;
}
<div class="loader"></div>
<div class="loader opp"></div>
我正在尝试创建如下所示的相同动画:
body {
text-align: center;
background: #222;
}
svg {
position: absolute;
display: block;
}
.container {
display: inline-block;
position: relative;
width: 50px;
}
.container #Layer_2 {
width: 60px;
stroke-dasharray: 121;
stroke-dashoffset: 121;
transform: rotate(270deg);
}
.container #Layer_2.on {
animation: circle 1.4s;
-webkit-animation-fill-mode: forwards;
animation-fill-mode: forwards;
}
@keyframes circle {
0% {
stroke-dashoffset: 121;
transform: rotate(90deg);
}
100% {
stroke-dashoffset: 0;
}
}
<div class="container">
<svg id="Layer_2" class="on" viewBox="0 0 50 50">
<defs>
<style>
.cls-1 {
fill: none;
stroke: #ddd;
stroke-miterlimit: 10;
stroke-width: 1px;
}
</style>
</defs>
<circle class="cls-1" cx="25" cy="25" r="19.27" />
</svg>
</div>
但是,理想情况下我不想使用 SVG。我的网站上已经有一个使用类似动画的微调器:
* {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
box-sizing: border-box;
font-family: "Avenir Next", sans-serif;
margin: 0;
outline: none;
padding: 0;
}
.spinner-wrapper {
display: inline-block;
position: relative;
width: 64px;
height: 64px;
animation: wrapper-rotate 1568ms linear infinite;
--spinner-border-width: 3px;
--spinner-color: black;
}
.spinner-wrapper .spinner {
position: absolute;
width: 100%;
height: 100%;
animation: fill-unfill-rotate 5332ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper {
display: block;
position: relative;
width: 50%;
height: 100%;
float: left;
overflow: hidden;
}
.spinner-wrapper .circle-clipper.circle-clipper-left .circle {
left: 0;
border-right-color: transparent !important;
transform: rotate(129deg);
animation: left-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper.circle-clipper-right .circle {
right: 0;
border-left-color: transparent !important;
transform: rotate(-129deg);
animation: right-spin 1333ms cubic-bezier(0.785, 0.135, 0.15, 0.86) infinite both;
}
.spinner-wrapper .circle-clipper .circle {
position: absolute;
top: 0;
right: 0;
bottom: 0;
width: 200%;
height: 100%;
border: var(--spinner-border-width) solid var(--spinner-color);
border-bottom-color: transparent !important;
border-radius: 50%;
}
.spinner-wrapper .gap-patch {
position: absolute;
top: 0;
left: 45%;
width: 10%;
height: 100%;
overflow: hidden;
}
.spinner-wrapper .gap-patch .circle {
width: 1000%;
left: -450%;
}
@keyframes wrapper-rotate {
to {
transform: rotate(360deg);
}
}
@keyframes fill-unfill-rotate {
12.5% {
transform: rotate(135deg);
}
25% {
transform: rotate(270deg);
}
37.5% {
transform: rotate(405deg);
}
50% {
transform: rotate(540deg);
}
62.5% {
transform: rotate(675deg);
}
75% {
transform: rotate(810deg);
}
87.5% {
transform: rotate(945deg);
}
to {
transform: rotate(1080deg);
}
}
@keyframes left-spin {
from {
transform: rotate(130deg);
}
50% {
transform: rotate(-5deg);
}
to {
transform: rotate(130deg);
}
}
@keyframes right-spin {
from {
transform: rotate(-130deg);
}
50% {
transform: rotate(5deg);
}
to {
transform: rotate(-130deg);
}
}
<div class="spinner-wrapper">
<div class="spinner">
<div class="circle-clipper circle-clipper-left">
<div class="circle"></div>
</div>
<div class="gap-patch circle-clipper">
<div class="circle"></div>
</div>
<div class="circle-clipper circle-clipper-right">
<div class="circle"></div>
</div>
</div>
</div>
上面的动画与我想要实现的类似,但显然它是无限的,并没有完全完成整个圆圈。
任何人都可以建议我可以对我现有的解决方案做些什么,以使其适应第一个动画吗?
我尝试了各种方法,但没有取得任何真正的进展。
我会考虑使用 clip-path
的想法,就像我在 this previous answer:
.loader {
width:150px;
height:150px;
display:inline-block;
margin:20px;
border:2px solid #fff;
border-radius:50%;
transform:scaleX(var(--s,1)) rotate(225deg);
clip-path:polygon(50% 50%,0 0,0 0,0 0, 0 0,0 0);
animation:change 1.4s linear forwards;
}
.opp {
--s:-1;
}
@keyframes change {
25% {
clip-path:polygon(50% 50%,0 0, 0 100%,0 100%,0 100%,0 100%);
}
50% {
clip-path:polygon(50% 50%,0 0,0 100%, 100% 100%, 100% 100%,100% 100%);
}
75% {
clip-path:polygon(50% 50%,0 0,0 100%,100% 100%, 100% 0,100% 0);
}
100% {
clip-path:polygon(50% 50%,0 0,0 100%,100% 100%, 100% 0, 0% 0%);
transform:scaleX(var(--s,1)) rotate(45deg);
}
}
body {
background:black;
}
<div class="loader"></div>
<div class="loader opp"></div>