仅使用CSS实现带有圆角和透明背景的绘制圆形动画

25
我正在尝试使用border-radius绘制一个圆形,并对其进行动画处理。我可以做到这一点,但我无法覆盖元素并将圆的背景设置为透明,而不必取消隐藏遮罩。我无法使其在元素上透明,因为需要应用遮罩来隐藏旋转的左半部分以模仿绘制效果。
HTML
<div class="background">
    <div class="wrapper">
        <div class="pie spinner"></div>
        <div class="pie filler"></div>
        <div class="mask"></div>
    </div>
</div>

CSS

.background{
    background:green;
    z-index: 1000;
}
.wrapper {
  width: 250px;
  height: 250px;
  position: relative;
  margin: 40px auto;
  background: rgba(0,0,255,1);

}

.wrapper, .wrapper * {
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
}
.wrapper .pie {
  width: 50%;
  height: 100%;
  transform-origin: 100% 50%;
  position: absolute;
  background: transparent;
  border: 5px solid rgba(0,0,0,0.9);
}

.wrapper .spinner {
  border-radius: 100% 0 0 100% / 50% 0 0 50%;
  z-index: 0;
  border-right: none;
  -webkit-animation: rota 5s linear infinite;
}

.wrapper:hover .spinner,
.wrapper:hover .filler,
.wrapper:hover .mask {
  animation-play-state: running;
}

.wrapper .filler {
  border-radius: 0 100% 100% 0 / 0 50% 50% 0;
  left: 50%;
  opacity: 0;
  -webkit-animation: opa 5s steps(1, end) infinite reverse;
  border-left: none;
}

.wrapper .mask {
  width: 50%;
  height: 100%;
  position: absolute;
  background: inherit;
  opacity: 1;
  -webkit-animation: opa 5s steps(1, end) infinite;
}

@-webkit-keyframes rota {
  0% {transform: rotate(0deg);border-color:red;}
  100% {transform: rotate(360deg);z-index:0;}
}
@-webkit-keyframes opa {
  0% {opacity: 1;}
  50%, 100% {opacity: 0;}
}

http://jsfiddle.net/BuzzSmarter/gmvban4p/

在我的例子中,我需要将蓝色背景变为透明,而不是在开始旋转之前取消边框半径。请原谅颜色,这不是我将要使用的颜色,但可以更清晰地解决问题。这是我的临时产品,在那里我必须删除绘图以实现透明度。http://jsfiddle.net/BuzzSmarter/gmvban4p/

相关:https://dev59.com/j3_aa4cB1Zd3GeqP0Tvs - Nikos M.
感谢您的建议@NikosM。但是相关问题并没有尝试解决我的问题。我需要圆形的内部是透明的。相关问题没有提到背景透明度。 - BuzzSmarter
我认为你可以使用类似于那个问题中的解决方案,并在动画圆圈内添加任何其他内容(因此它覆盖了光盘的背景,只有周长可见)。 - Nikos M.
我认为目前仅使用CSS不可能实现。否则,您可以在CSS中使用矢量图形,如SVG,并在SVG中动画化弧线。 - Nikos M.
1个回答

60

这是我的解决方案。

我设置了body的背景,以显示其为透明的。

body {
  background: repeating-linear-gradient(45deg, white 0px, lightblue 100px);
  height: 500px;
  background-size: 500px 500px;
  background-repeat: no-repeat;
}

html {
  height: 100%;
}

#container {
  position: absolute;
  width: 400px;
  height: 400px;
   border: solid red 1px;
   animation: colors 4s infinite;
}

#halfclip {
  width: 50%;
  height: 100%;
  right: 0px;
  position: absolute;
   overflow: hidden;
   transform-origin: left center;
   animation: cliprotate 16s steps(2) infinite;
   -webkit-animation: cliprotate 16s steps(2) infinite;
}

.halfcircle {
  box-sizing: border-box;
  height: 100%;
  right: 0px;
  position: absolute;
  border: solid 25px transparent;
   border-top-color: blue;
   border-left-color: blue;
   border-radius: 50%;
}
#clipped {
  width: 200%;
   animation: rotate 8s linear infinite;
   -webkit-animation: rotate 8s linear infinite;
}
#fixed {
  width: 100%;
    transform: rotate(135deg);  
   animation: showfixed 16s steps(2) infinite;
   -webkit-animation: showfixed 16s linear infinite;
}

@-webkit-keyframes cliprotate {
  0% {transform: rotate(0deg);}
  100% {transform: rotate(360deg);}
}

@keyframes cliprotate {
  0% {transform: rotate(0deg);}
  100% {transform: rotate(360deg);}
}


@-webkit-keyframes rotate {
  0% {transform: rotate(-45deg);}
  100% {transform: rotate(135deg);}
}

@keyframes rotate {
  0% {transform: rotate(-45deg);}
  100% {transform: rotate(135deg);}
}

@-webkit-keyframes showfixed {
  0% {opacity: 0;}
  49.9% {opacity: 0;}
  50% {opacity: 1;}
 100% {opacity: 1;}
}
<div id="container">
    <div id="halfclip">
        <div class="halfcircle" id="clipped">
        </div>
    </div>
    <div class="halfcircle" id="fixed">
    </div>
</div>

这是对解决方案的改进,使其只在鼠标悬停时运行一次

body {
  background: repeating-linear-gradient(45deg, white 0px, lightblue 100px);
  height: 500px;
  background-size: 500px 500px;
  background-repeat: no-repeat;
}

html {
  height: 100%;
}

#container {
  position: absolute;
  width: 300px;
  height: 300px;
   border: solid red 1px;
}

#halfclip {
    width: 50%;
    height: 100%;
    right: 0px;
    position: absolute;
    overflow: hidden;
    transform-origin: left center;
}

#container:hover #halfclip {
    animation: cliprotate 6s 1;
    transform: rotate(180deg);
} 

@keyframes cliprotate {
  0% {transform: rotate(0deg);}
  50% {transform: rotate(0deg);}
  50.01% {transform: rotate(180deg);}
  100% {transform: rotate(180deg);}
}

.halfcircle {
  box-sizing: border-box;
  height: 100%;
  right: 0px;
  position: absolute;
  border: solid 25px transparent;
   border-top-color: blue;
   border-left-color: blue;
   border-radius: 50%;
}

#clipped {
    width: 200%;
    transform: rotate(-45deg);
}
#container:hover #clipped {
    transform: rotate(135deg);
    animation: rotate 3s linear 2;
}


@keyframes rotate {
  0% {transform: rotate(-45deg);}
  100% {transform: rotate(135deg);}
}


#fixed {
  width: 100%;
    transform: rotate(135deg);  
    opacity: 0;
}

#container:hover #fixed {
    opacity: 1;
    animation: showfixed 6s 1;
}



@keyframes showfixed {
  0% {opacity: 0;}
  49.99% {opacity: 0;}
  50% {opacity: 1;}
 100% {opacity: 1;}
}
<div id="container">
    <div id="halfclip">
        <div class="halfcircle" id="clipped">
        </div>
    </div>
    <div class="halfcircle" id="fixed">
    </div>
</div>


正是我所寻找的。不知道为什么它还没有被标记为答案。 - user1017882
哇,这太棒了,正是我在寻找的。您如何使其仅运行一次,并在完成后保持完整圆形?我尝试使用JavaScript事件侦听器开发一种方法,以便在动画完成时侦听并相应地旋转半圆以获得完整圆形,但我遇到的问题是事件触发时和JavaScript运行变换之间存在一些延迟时间... 动画将完成,然后CSS将给出其初始值,然后一两秒钟后JavaScript将运行,圆圈看起来就像整个圆形。 - nyduss
1
@nyduss 我添加了另一个示例,基于更改容器悬停时的属性,并仅运行一次动画。 - vals
所以我进一步加入了一些很酷的新功能。我使用jQuery添加了一个轨道和一些按钮来控制动画的播放状态。这是我“摆弄”的所有新东西的链接https://jsfiddle.net/3hwoxxpp/如果动画在您的浏览器上无法正常工作,对不起...我只添加了Webkit动画,因为我有点懒 >.< 享受吧! - nyduss
这太棒了(我正在CodePen上玩弄它,试图理解这里发生了什么); - L777
这些颜色/轮廓使得理解变得更加容易:代码笔链接 - L777

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接