Drawing animated arc with pure CSS

后端 未结 6 1768
挽巷
挽巷 2020-12-30 06:22

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:

.         


        
相关标签:
6条回答
  • 2020-12-30 06:37

    I may be a little late, but I think using two "hiders" and translating one up and one down will look a little better.

    Working Example

    <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);
        }
    }
    
    0 讨论(0)
  • 2020-12-30 06:40

    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:

    http://jsfiddle.net/AZb3X/

    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>
    
    0 讨论(0)
  • 2020-12-30 06:41

    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>

    0 讨论(0)
  • 2020-12-30 06:50

    EDIT: Using two arcs, you can have the animation draw cleanly from left-to-right AND have the background show through:

    http://jsfiddle.net/sPv4A/6/

    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 divs 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>

    0 讨论(0)
  • 2020-12-30 06:52

    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>

    On JSFiddle

    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.

    0 讨论(0)
  • 2020-12-30 06:57

    You might want to check out this article, Chris Coyier has done a article on pie chart animation which is basically the same as your demo if you remove the light blue background.enter image description here

    Article: http://css-tricks.com/css-pie-timer/

    Demo: http://codepen.io/HugoGiraudel/pen/BHEwo

    0 讨论(0)
提交回复
热议问题