Можно ли нарисовать частичный контур круга в CSS (форма открытого кольца)?

Я заинтересован в создании счетчика загрузки полностью в CSS, но для этого мне нужно было бы нарисовать форму открытого кольца следующим образом:

введите описание изображения здесь

Кольцо будет обводить себя по окружности круга. Возможно ли это в CSS?


person colindunn    schedule 14.02.2017    source источник
comment
Вы можете стилизовать круг SVG с помощью stroke-dasharray. Он анимирован и может использоваться как в CSS, так и в качестве атрибута: developer.mozilla.org/en-US/docs/Web/SVG/Attribute/   -  person jaboja    schedule 14.02.2017
comment
@ JakubJagiełło Это позволит мне нарисовать границу по окружности круга?   -  person colindunn    schedule 14.02.2017
comment
Хитрость заключается в том, что вы, по сути, оформляете границу по окружности, чтобы она была пунктирной линией с одним тире, и, анимируя эту длину тире, вы можете создать эффект растущей вокруг линии.   -  person jaboja    schedule 14.02.2017
comment
@colindunn Я обновил свой ответ, чтобы он работал примерно так же, используя SVG и stroke-dasharray. Вероятно, это единственный способ нарисовать контур круга, используя только HTML и CSS.   -  person Dylan Stark    schedule 14.02.2017


Ответы (4)


Чтобы создать круг, который постепенно прорисовывает его внешний путь, используйте SVG.

Свойство SVG stroke-dasharray превратит любой путь в пунктирную линию, которую вы можете использовать в своих интересах, установив размер тире почти равным длине самого пути.

Затем используйте CSS-анимацию, чтобы постепенно изменять stroke-dashoffset, перемещая черту по периметру вашего круга.

circle {
  fill: white;
  stroke: black;
  stroke-width: 2;
  stroke-dasharray: 250;
  stroke-dashoffset: 1000;
  animation: rotate 5s linear infinite;
}

@keyframes rotate {
  to {
    stroke-dashoffset: 0;
  }
}
<svg height="100" width="100">
  <circle cx="50" cy="50" r="40" />
</svg>

person Dylan Stark    schedule 14.02.2017

Статическое изображение

Упрощенный пример, который полагается только на один элемент HTML и класс CSS, может выглядеть следующим образом:

.arc {
  /* Border size and color */
  border: 2px solid #000;
  /* Creates a circle */
  border-radius: 50%;
  /* Circle size */
  height: 100px;
  width: 100px;
  /* Use transparent borders to define opening (more transparent = larger opening) */
  border-top-color: transparent;
  border-left-color: transparent;
  /* Use transform to rotate to adjust where opening appears */
  transform: rotate(300deg)
}

Пример

введите описание изображения здесь

.arc {
  border: 2px solid #000;
  border-radius: 50%;
  height: 100px;
  width: 100px;
  border-top-color: transparent;
  transform: rotate(300deg)
}
<div class='arc'></div>

Поворот изображения

Вы можете применить базовое вращение к предыдущему статическому примеру, воспользовавшись преимуществами анимации на основе CSS, используя @keyframes:

.arc {
  /* Border size and color */
  border: 2px solid #000;
  /* Creates a circle */
  border-radius: 50%;
  /* Circle size */
  height: 100px;
  width: 100px;
  /* Use transparent borders to define opening (more transparent = larger opening) */
  border-top-color: transparent;
  /* Rotate indefinitely (longer time = slower rotation) */
  animation: rotate 2s infinite linear;
}

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

Пример

введите описание изображения здесь

.arc {
  border: 2px solid #000;
  border-radius: 50%;
  height: 100px;
  width: 100px;
  border-top-color: transparent;
  animation: rotate 2s infinite linear;
}

@keyframes rotate {
  0%    { transform: rotate(0deg);  }
  100%  { transform: rotate(360deg);  }
}
<div class='arc'></div>

Рисование (без SVG)

Другой подход, , с которым я столкнулся, хотя и далеко не такой элегантный, как предыдущие подходы, кажется, для достижения желаемого эффекта. Он предполагает использование нескольких анимаций, а также отображение / скрытие различных участков круга по мере необходимости.

Фрагмент кода содержит пример, демонстрирующий это.

Пример

введите описание изображения здесь

#container {
  position: absolute;
  width: 100px;
  height: 100px;
  animation: colors 1s infinite;
}
#halfclip {
  width: 50%;
  height: 100%;
  right: 0px;
  position: absolute;
  overflow: hidden;
  transform-origin: left center;
  animation: cliprotate 4s steps(2) infinite;
  -webkit-animation: cliprotate 4s steps(2) infinite;
}
.halfcircle {
  box-sizing: border-box;
  height: 100%;
  right: 0px;
  position: absolute;
  border: solid 2px transparent;
  border-top-color: #000;
  border-left-color: #000;
  border-radius: 50%;
}
#clipped {
  width: 200%;
  animation: rotate 2s linear infinite;
  -webkit-animation: rotate 2s linear infinite;
}
#fixed {
  width: 100%;
  transform: rotate(135deg);
  animation: showfixed 4s steps(2) infinite;
  -webkit-animation: showfixed 4s 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>

Рисование (с SVG)

Использование SVG, вероятно, является лучшим способом решения этой проблемы, поскольку он явно предназначен для обработки рисования в браузере. Я настоятельно рекомендую этот подход, если доступна поддержка SVG.

В ответе Дилана подробно описано, как может выглядеть эта реализация.

person Rion Williams    schedule 14.02.2017
comment
Это дает мне статическое представление 3/4 полного круга, но не позволяет мне плавно рисовать контур по окружности. - person colindunn; 14.02.2017
comment
Ах, кажется, я неправильно понял, что вы искали. Вы можете анимировать тот же пример, представленный с использованием ключевых кадров (то есть, чтобы данный значок вращался бесконечно). Вы хотите, чтобы круг превратился в единственную точку, нарисуйте круг и затем начните снова? - person Rion Williams; 14.02.2017
comment
@RionWilliams, ничего себе, метод рисования без SVG - это безумие! Я бы не подумал, что это возможно, блестящая идея для того, кто ее придумал. - person Dylan Stark; 14.02.2017
comment
Да, это довольно дико :) - person Rion Williams; 14.02.2017

Чтобы создать открытая часть, просто перекрывающая круговой элемент. Преимущество в том, что открытая часть может быть сколь угодно длинной (не ограничиваясь 3/4 полного круга).

.circle {
  width: 100px;
  height: 100px;
  border: 2px solid;
  border-radius: 50%;
  margin: 30px;
  animation: rotate 1s infinite linear;
}
.circle::after {
  content: "";
  display: block;
  width: 80px;
  height: 80px;
  background: white;
  border-radius: 50%;
  margin: -30% 0 0 -30%;
}
@keyframes rotate {
  0%    { transform: rotate(0deg);  }
  100%  { transform: rotate(360deg);  }
}
<div class="circle"></div>

person andreas    schedule 14.02.2017

для псевдо-версии вы также можете использовать linear-gradient (оттенок может быть уменьшен или увеличен) и background-clip,

там, где это возможно, mix-blend-mode может сделать его полупрозрачным,

currentcolor и animation также можно использовать для анимации цвета:

.loader {
  font-size: 1.5em;
  color: gray;
  position: relative;
  padding: 3px;
  /* make a square */
  height: 100px;
  width: 100px;
  /* center content*/
  display: flex;
  align-items: center;
  justify-content: center;
  animation: coloranim infinite 5s;
}

.circle {
  border-radius: 100%;
  overflow: hidden;
}

.loader:after {
  border-radius: inherit;
  color: inherit;
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 3px;
  background: linear-gradient(white, white), linear-gradient(0deg, transparent 40%, currentcolor 60%), linear-gradient(50deg, transparent 50%, currentcolor 52%);
  background-clip: content-box, border-box, border-box;
  z-index: -1;
  mix-blend-mode: multiply;/* if avalaible, else bg remains white */
}

.spin:after {
  animation: spin 2s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

@keyframes coloranim {
  20% {
    color: tomato;
  }
  40% {
    color: purple;
  }
  60% {
    color: turquoise;
  }
  80% {
    color: green;
  }
}


/* demo purpose, use your own style wherever your loader is needed */

html {
  height: 100%;
  display: flex;
  background: url(http://lorempixel.com/800/800/food/3);
  background-size: cover;
  box-shadow: inset 0 0 0 2000px rgba(255, 255, 255, 0.3)
}

body {
  margin: auto;
}
<div class="spin circle loader coloranim"> loading... </div>

http://codepen.io/gc-nomade/pen/YNbmGE

person G-Cyrillus    schedule 19.02.2017