【问题标题】:Adapt CSS Spinner Animation to Finish instead of Repeat调整 CSS Spinner 动画以完成而不是重复
【发布时间】:2020-04-26 19:35:38
【问题描述】:

我正在尝试创建如下所示的相同动画:

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>

上面展示的动画与我想要实现的相似,但显然它是无限的,并没有完全完成整个循环。

谁能建议我可以对我现有的解决方案做些什么以使其适应第一个动画?

我尝试了各种方法,但未能取得任何实际进展。

【问题讨论】:

  • 我知道您明确要求调整现有代码,但您是否愿意改用新代码(具有所需行为)?
  • @Richard 当然 :-D!我只是想避免 SVG 实现...

标签: css css-animations css-transitions spinner


【解决方案1】:

我会考虑使用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>

【讨论】:

  • 这太棒了!比我正在研究的解决方案要好得多...jsfiddle.net/su6yqkdg
  • 我会对此进行一些测试,然后在我需要时接受它:-D - 非常感谢!
猜你喜欢
  • 2017-07-11
  • 2021-05-31
  • 2016-01-26
  • 2014-01-16
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多