it-swarm.com.ru

Рисование анимированной дуги с использованием чистого CSS

Я знаю, что можно рисовать и анимировать дуги в svg и canvas. Однако возможно ли это в css?

Я создал дугу, используя следующий метод:

.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;
}

Оригинальная скрипка: http://jsfiddle.net/YGKWT/ (Неработающей ссылке)

Но как я могу оживить это? Единственный способ, которым я могу придумать, это иметь чистый белый div над ним и сдвигать этот div вправо, постепенно раскрывая дугу. Есть ли способ лучше?

Правка:

Вот тип анимации, которую я ищу: http://jsfiddle.net/nQLY7/ (Неработающей ссылке)

11
Conqueror

Возможно, вы захотите проверить эту статью, Крис Койер (Chris Coyier) написал статью об анимации круговой диаграммы, которая в основном совпадает с вашей демонстрацией, если вы удалите светло-синий фон.enter image description here

Статья: http://css-tricks.com/css-pie-timer/

Демо: http://codepen.io/HugoGiraudel/pen/BHEwo

8
iConnor

Вот рабочая демка с минимумом жестко закодированных переменных. Это работает на основе анимированных половинок круга:

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

Также выглядит так же, как ответ iConnor но не имеет недостатка в жестко закодированном 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>

3
Vadim Ovchinnikov

Если вам нужен только CSS3, вы можете установить width + height, установить border-radius в 100%, отключить дополнительные границы (используйте только 1 или 2) и добавить к нему несколько хороших пикселей.

Затем вы можете анимировать, используя animate: time animation ease timingFunction; Объявите анимацию, используя @-prefix-keyframes { . . . } (да, похоже, что большинству браузерных движков для этого нужен префикс, chrome делает: S) Я думаю, что у меня может быть что-то близкое к тому, что вы имеете в виду: 

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

На JSFiddle

Не стесняйтесь использовать и модифицировать .. В качестве альтернативы вы можете проверить что-то с SVG, это довольно прилично и поддерживается большинством современных браузеров.

2
Felype

Правка: Используя две дуги, вы можете сделать анимацию отрисовки чисто слева направо И фон сквозь:

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

Префиксы поставщиков не включены в 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>

СТАРЫЙ ОТВЕТ: Может быть, использовать два дочерних divs, чтобы скрыть это, а затем уменьшить их, чтобы показать это:

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

1
Ben Jackson

Возможно, я немного опоздал, но я думаю, что использование двух «скрывателей» и перевод одного вверх и другого вниз будет выглядеть немного лучше. 

Рабочий пример

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