Круговой индикатор процесса на CSS

Что будем делать?

Такие индикаторы загрузки вы наверняка встречали, особенно на Flash сайтах. Это сектор круга, который становится все больше и больше, пока не превратится в завершенный круг.

Индикатор         загрузки

На первый взгляд задача кажется простой: делаем круг, вращаем его и скрываем часть за маской. Но на деле все оказывается несколько сложнее. CSS не подготовлен для решения таких задач, даже при использовании препроцессоров наподобие  SASS & Compass. Мы всегда боремся, когда приходится делать различные формы, а особенно при определении стилей и анимации для них. Большая часть рабочего времени уходит на то. чтобы получить что-то работающее, а в жертву приносится семантичность кода и его поддержка.

demosourse

 

Зачем делаем?

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

Хотя есть несколько изумительных инструментов для управления круговыми диаграммами (в основном, на JavaScript), мы тем не менее сделаем такой элемент только на CSS и даже анимируем его с помощью нескольких трюков.

Семантичность кода будет так себе! Но сопровождение можно сделать достаточно удобным.

 

HTML

Нам нужно 3 разных элемента:

  • spinner: половинка круга, которая будет вращаться;
  • mask: данный элемент скрывает вращающийся круг в ходе первых 50% анимации;
  • filler: данный элемент заполняет круг в ходе последних 50% анимации.

И все три элемента должны иметь одного родителя для абсолютного позиционирования:

<div class="wrapper">
  <div class="spinner pie"></div>
  <div class="filler pie"></div>
  <div class="mask"></div>
</div>

Так как spinner и filler являются двумя половинками одного круга, то мы будем использовать для них класс .pie.

 

CSS

Чтобы сохранить код урока четким и понятным, префиксы производителей браузеров опущены.

Родительский элемент получает размеры и абсолютное позиционирование контекста для таймера:

.wrapper {
  width: 250px;
  height: 250px;
  position: relative;
  background: white;
}

Важно, чтобы ширина и высота были равны, чтобы получить круг и все работало.

Элементы "spinner" и "filler" используют данный код CSS:

.pie {
  width: 50%;
  height: 100%;
  position: absolute;
  background: #08C;
  border: 10px solid rgba(0,0,0,0.4);
}

Они имеют ширину равную 50% родительского элемента, так они являются двумя частями одного круга, а их высота равна высоте родительского элемента. Также мы определяем для них одинаковый цвет и рамку.

 

Элемент "spinner"

.spinner {
  border-radius: 125px 0 0 125px;
  z-index: 200;
  border-right: none;
  animation: rota 10s linear infinite;
}

Делаем его полукругом с помощью свойства border-radius на верхнем левом и нижнем левом углах. Также определяем положительное значение для z-index, чтобы разместить его поверх заполняющего элемента, но ниже маски.

Затем добавляем animation длительностью 10 секунд. Об анимации мы поговорим позже.

 

Элемент "filler"

.filler {
  border-radius: 0 125px 125px 0;
  z-index: 100;
  border-left: none;
  animation: fill 10s steps(1, end) infinite;
  left: 50%;
  opacity: 0;
}

Для данного элемента устанавливаем border-radius и z-index, удаляем border-left, и делаем анимацию длительностью 10секунд. Для данного элемента animation-timing-function не получает значения linear, но будет steps(1, end). Это значит, что animation будет выполняться мгновенно.

Так как заполняющий элемент не должен быть видимым в ходе первой половины анимации, его непрозрачность будет 0, а положение - 50% ширины родительского элемента.

 

Элемент "mask"

.mask {
  width: 50%;
  height: 100%;
  position: absolute;
  z-index: 300;
  opacity: 1;
  background: inherit;
  animation: mask 10s steps(1, end) infinite;
}

Маска присутствует с начала анимации, поэтому ее непрозрачность имеет значение 1, а фон наследуется от родительского элемента (чтобы она была невидима). Чтобы закрывать вращающийся элемент, она будет иметь те же размеры, а свойство z-index устанавливается в значение 300.

 

Кадры анимации

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

@keyframes fill {
  0%        { opacity: 0; }
  50%, 100% { opacity: 1; }
}

@keyframes mask {
  0%        { opacity: 1; }
  50%, 100% { opacity: 0; }
}

Первая анимация (rota) используется для элемента spinner. Он постепенно вращается от 0 до 360 градусов за 10 секунд.

Вторая анимация (fill) используется для элемента filler. Он немедленно изменяет непрозрачность с 0 до 1 по истечении 5 секунд.

Последняя анимация (mask) используется для элемента mask. Он немедленно изменяет непрозрачность с 1 до 0 по истечении 5 секунд.

Анимация имеет следующий вид:

  • T0 - элемент spinner слева, скрыт маской . Элемент filler скрыт.
  • T1 - элемент spinner начинает вращаться по часовой стрелке и медленно появляется из-за маски.
  • T2 - элемент spinnerr повернут на угол 360/10*2 = 72° продолжает вращаться.
  • T3 - элемент spinner повернут на угол 360/10*3 = 108° продолжает вращаться.
  • T4 - элемент spinner повернут на угол 360/10*4 = 144° продолжает вращаться.
  • T5 - элемент spinner повернут на угол 360/10*5 = 180° продолжает вращаться. В данный момент элемент filler мгновенно становится видимым, а маска скрывается.
  • T6 - элемент spinner повернут на угол 360/10*6 = 216° продолжает вращаться.
  • T7 - элемент spinner повернут на угол 360/10*7 = 252° продолжает вращаться.
  • T8 -элемент spinner повернут на угол 360/10*8 = 288° продолжает вращаться.
  • T9 - элемент spinner повернут на угол 360/10*9 = 324° продолжает вращаться.
  • T10 - элемент spinner повернут на угол 360°. Вернулись к точке старта. Сбрасываем анимацию. Маска появляется, а заполняющий элемент скрывается.

 

Бонус

Несколько дополнительных трюков.

Пауза при наведении курсора

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

С помощью данного кода вы можете остановить всю анимацию при наведении курсора на родительский элемент.

 

Вставляем содержание

Благодаря свойству z-index мы можем легко добавить какое-нибудь содержание в элемент spinner и заставить его вращаться. Попробуйте следующий код :

.spinner:after {
  content: "";
  position: absolute;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  top: 10px;
  right: 10px;
  background: #fff;
  border: 1px solid rgba(0,0,0,0.4);
  box-shadow: inset 0 0 3px rgba(0,0,0,0.2);
}

Препроцессор или переменные CSS

В текущий момент код очень не просто поддерживать. Но если мы используем переменные (в препроцессоре или ожидаемые внутренние переменные CSS), все может стать существенно проще. Например, можно добавить переменные для управления длительностью вместо того, чтобы исправлять код в 3 определениях анимаций.

Если хочется улучшить сопровождаемость кода без использования препроцессоров, можно создать класс с одним управлением длительностью анимаций и добавлять его к 3 дочерним элементам. Например так :

.animation-duration {
  animation-duration: 10s;
}

 

<div class="wrapper">
  <div class="spinner pie animation-duration"></div>
  <div class="filler pie animation-duration"></div>
  <div class="mask animation-duration"></div>
</div>

 

Недостатки

Данная техника имеет ряд недостатков:

  • Не поддерживаются градиенты.
  • Не поддерживаются тени.
  • Нет адаптивности. Если изменяется размер родительского элемента, то все будет нормально, кроме радиуса закругления рамки. Его придется менять вручную.
  • Нет семантичности (4 элемента для одной анимации).

 

Поддержка браузеров

Так как мы используем анимации CSS, то поддержка в браузерах достаточно скудная:

  • Internet Explorer 10
  • Firefox 12+
  • Chrome
  • Safari 5+
  • Opera 12+
  • iOS Safari 3+
  • Android 2+

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: css-tricks.com/css-pie-timer/
Перевел: Сергей Фастунов
Урок создан: 8 Августа 2012
Просмотров: 35449
Правила перепечатки


5 последних уроков рубрики "CSS"

или авторизуйтесь, чтобы добавлять комментарии, оценивать уроки и сохранять их в личном кабинете
  • 14 Августа 2012 15:12
    user46577
    В опере работает.
  • 14 Августа 2012 16:00
    sam2019
    В 14-ё мозиле тоже. Думаю все равно лучше использовать картинки, но для общего развития можно и попробывать...
  • Комментарий удален
    • 15 Августа 2012 10:49
      ppaull
      +++ ... как и 95% выкладываемых здесь примеров
      • 15 Августа 2012 15:10
        Clever_Bobr
        Если вам не нравится! То не заходите на сайт! И не надо тут портить впечатление о сайте! Мне сайт нравится! Много полезного. Всем советую!
^ Наверх ^