Reputation: 4433
I know it is possible to draw and animate arcs in SVG and canvas. However, is it possible in CSS?
I have created an arc using the following method:
.arc{
width:150px;
height:400px;
border-radius:50%;
border-right:1px solid black;
border-left:1px solid black;
border-top:1px solid black;
border-bottom:1px solid white;
}
But, how can I animate this? The only way I can think of is having a pure white div over it and sliding that div to the right gradually revealing the arc. Is there a better way?
Upvotes: 13
Views: 52045
Reputation: 11922
EDIT: Using two arcs, you can have the animation draw cleanly from left-to-right AND have the background show through:
Vendor prefixes not included for CSS:
.arcContain {
width: 150px;
height: 400px;
position: relative;
margin: 20px;
}
.arc {
width: 150px;
height: 400px;
border-radius: 50%;
border: 2px solid black;
border-bottom: 2px solid transparent;
position: absolute;
top: 0;
right: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.archideLeft .arc {
top: auto;
bottom: 0;
right: auto;
left: 0;
}
.archide {
width: 50%;
height: 0%;
position: absolute;
top: 0;
right: 0;
overflow: hidden;
animation: appear 1.2s ease-in 1.2s forwards;
}
.archideLeft {
top: auto;
bottom: 0;
right: auto;
left: 0;
animation: appear 1.2s ease-out forwards;
}
@keyframes appear {
to {
height: 100%;
}
}
<div class="arcContain">
<div class="archide archideLeft">
<div class="arc"></div>
</div>
<div class="archide">
<div class="arc"></div>
</div>
</div>
OLD ANSWER: Maybe using two child div
s to cover it up, and then have them shrink away to reveal it:
.arc {
width: 150px;
height: 400px;
border-radius: 50%;
border-right: 1px solid black;
border-left: 1px solid black;
border-top: 1px solid black;
border-bottom: 1px solid white;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
position: relative;
}
.arcInner {
background: white;
height: 402px;
width: 77px;
position: absolute;
}
.arcLeft {
top: -2px;
left: -2px;
-webkit-transition: height 2s linear;
-moz-transition: height 2s linear;
-ms-transition: height 2s linear;
-o-transition: height 2s linear;
transition: height 2s linear;
}
.arcRight {
bottom: 0;
right: -2px;
-webkit-transition: height 2s 2s linear;
-moz-transition: height 2s 2s linear;
-ms-transition: height 2s 2s linear;
-o-transition: height 2s 2s linear;
transition: height 2s 2s linear;
}
.appear .arcInner {
height: 0;
}
<div class="arc">
<div class="arcInner arcLeft"></div>
<div class="arcInner arcRight"></div>
</div>
Upvotes: 1
Reputation: 3136
If you need sole CSS3, then you can set a width
+height
, set border-radius
to 100%
, disable the extra borders (use only 1 or 2) and add some good pixels to it.
Then you can animate using animate: time animation ease timingFunction;
Declare the animation itself using @-prefix-keyframes { . . . }
(Eh yea, looks like most browser engines require prefix for this one, chrome does :S)
I think I might have something close to what you mean:
.qLoader2 {
border: 4px solid blue;
width: 10vw;
height: 10vw;
width: 72px;
height: 72px;
position: absolute;
top: 12vh;
right: 45vw;
left: 45vw;
background: white;
opacity: 0.45;
border-right: none;
border-top: none;
border-left: none;
z-index: 2000;
background-color: transparent;
border-radius: 100%;
transform: rotateZ(0);
-webkit-animation: spin 2s linear infinite;
animation: spin 2s linear infinite;
}
/* @-moz-keyframes spin { . . . } */
/* @-ms-keyframes spin { . . . } */
/* @-o-keyframes spin { . . . } */
@-webkit-keyframes spin {
from {
transform: rotateZ(0deg) scale(1);
}
50% {
transform: rotateZ(540deg) scale(0.9);
border-color: #0099ff;
}
to {
transform: rotateZ(1080deg) scale(1);
}
}
@keyframes spin {
from {
transform: rotateZ(0deg) scale(1);
}
50% {
transform: rotateZ(540deg) scale(0.9);
border-color: #0099ff;
}
to {
transform: rotateZ(1080deg) scale(1);
}
}
<div class="qLoader2"></div>
Feel free to use and modify. Alternatively you could check something with SVG it's fairly decent as well and supported by most nowadays browsers.
Upvotes: 3
Reputation: 14012
Here is working demo with minimum of hard-coded variables. This works based on animated circle halves:
.circle {
display: inline-flex;
overflow: hidden;
}
.circle__half {
height: 200px;
width: 100px;
position: relative;
overflow: hidden;
}
.circle__half:before {
height: inherit;
width: inherit;
position: absolute;
content: "";
border-radius: 100px 0 0 100px;
background-color: lime;
transform-origin: 100% 50%;
/* hidden by default */
transform: rotate(180deg);
opacity: 0.65;
animation-name: rotate-circle-half;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.circle__half--right {
transform: scale(-1, -1);
}
.circle .circle__half--right:before {
animation-name: rotate-circle-half--right;
}
/* show half of circle half of the time */
@keyframes rotate-circle-half {
0% {
transform: rotate(180deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(0deg);
}
}
@keyframes rotate-circle-half--right {
0% {
transform: rotate(180deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(0deg);
}
}
<div class="circle">
<div class="circle__half"></div>
<div class="circle__half circle__half--right"></div>
</div>
Also the same look as iConnor's answer but doesn't have drawback of hardcoded background-color
:
*,
*:before,
*:after {
box-sizing: border-box;
}
.circle {
display: inline-flex;
overflow: hidden;
}
.circle__half {
height: 200px;
width: 100px;
position: relative;
overflow: hidden;
}
.circle__half:before {
height: inherit;
width: inherit;
position: absolute;
content: "";
border-radius: 100px 0 0 100px;
border: 10px solid #00507c;
border-right-color: transparent;
background-color: #0087cf;
transform-origin: 100% 50%;
/* hidden by default */
transform: rotate(180deg);
opacity: 0.65;
animation-name: rotate-circle-half;
animation-duration: 4s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.circle__half--right {
transform: scale(-1, -1);
}
.circle .circle__half--right:before {
animation-name: rotate-circle-half--right;
}
/* show half of circle half of the time */
@keyframes rotate-circle-half {
0% {
transform: rotate(180deg);
}
50% {
transform: rotate(0deg);
}
100% {
transform: rotate(0deg);
}
}
@keyframes rotate-circle-half--right {
0% {
transform: rotate(180deg);
}
50% {
transform: rotate(180deg);
}
100% {
transform: rotate(0deg);
}
}
<div class="circle">
<div class="circle__half"></div>
<div class="circle__half circle__half--right"></div>
</div>
Upvotes: 6
Reputation: 16170
I may be a little late, but I think using two "hiders" and translating one up and one down will look a little better.
<div class="wrap">
<div class="arc"></div>
</div>
body {
background:orange;
}
.wrap {
position:absolute;
height:400px;
width:170px;
overflow: hidden;
}
.arc {
position:absolute;
width:150px;
height:400px;
margin:10px;
border-radius:50%;
border-right:1px solid black;
border-left:1px solid black;
border-top:1px solid black;
border-bottom:1px solid transparent;
}
.arc:before {
content:"";
position:absolute;
left:-1px;
top:-2px;
background: orange;
width:76px;
height:375px;
animation:unhide1 5s linear both;
}
.arc:after {
content:"";
position:absolute;
left:75px;
top:-2px;
background: orange;
float: right;
width:76px;
height:375px;
animation: unhide2 5s linear 5s both;
}
@keyframes unhide1 {
100% {
transform: translatey(-375px);
}
}
@keyframes unhide2 {
100% {
transform: translatey(375px);
}
}
Upvotes: 0
Reputation: 4433
As Per Chris B's suggestion on the original question, the answer is to contain the arc in another div and then animate the width of the container:
CSS:
body{
background:orange;
}
.arc{
width:150px;
height:400px;
border-radius:50%;
border-right:1px solid black;
border-left:1px solid black;
border-top:1px solid black;
border-bottom:1px solid white;
float:left;
}
.hider{
width:0px;
overflow:hidden;
-webkit-animation:unhide 12s;
}
@-webkit-keyframes unhide{
100%{width:400px}
}
HTML:
<div class='hider'>
<div class="arc"></div>
</div>
Upvotes: 0