null

Круглый прогресс бар на SVG

Сверстать можно практически что угодно, но иногда реализация дизайнерской задумки может привести к настолько сложной вёрстке, что становится проще “нарисовать” всё необходимое. Есть как минимум два способа это сделать: canvas и SVG-графика. Canvas - это тег HTML5 на котором изображения создаются посредством JavaScript. В отличие от него SVG является языком разметки подобным HTML, а значит имеет знакомый верстальщику вид. Кроме того, для SVG применимы  CSS-стили.

Один из примеров удачного использования SVG - создание круглого прогресс бара. Эту задачу можно решить как на чистом CSS, так и с использованием canvas, но мне вариант на SVG кажется наиболее красивым.

Для начала научимся рисовать окружность и её часть.

<html>
  <head>
    <style>
      svg {
        width: 200px; /* могут быть любыми */
        height: 200px;
      }
    </style>
  </head>

  <body>
    <svg viewbox="0 0 200 200">
      <circle r="80" cx="100" cy="100" fill="none" stroke-width="12" stroke="#ccc"/>
    </svg>
    <svg viewbox="0 0 200 200">
      <circle r="80" cx="100" cy="100" fill="none" stroke-width="12" stroke="orangered"
              stroke-linecap="round" stroke-dasharray="226 502,4"/>
    </svg>
    <svg viewbox="0 0 200 200">
      <circle r="80" cx="100" cy="100" fill="none" stroke-width="12" stroke="orangered"
              stroke-linecap="round" stroke-dasharray="226 502.4"
              stroke-dashoffset="-45" />
    </svg>
  </body>
</html>

 

Код выше описывает svg-документ размерами 200px на 200px, по центру которого нарисована окружность радиусом 80px. Изображение можно легко масштабировать с помощью CSS атрибутов width и height, не меняя размеры внутри SVG-тегов. При этом качество векторной графики не пострадает.

 

 

Для заполнения части окружности используют пунктирную линию в качестве границы. Параметры пунктира описываются атрибутом stroke-dasharray, где первый параметр задаёт длину штриха, второй - расстояние между штрихами. Рассчитываются они исходя из длины окружности (L=2πR).

В нашем случае длина окружности радиусом 80 составит 502,4. Тогда 1% будет соответствовать длине пунктира 502,4 / 100 * 1 = 5.

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

Наложим эти круги друг на друга и добавим текст.
 

<html>
  <head>
    <style>
      svg {
        width: 200px; /* могут быть любыми */
        height: 200px;
      }
    </style>
  </head>

  <body>
    <svg viewbox="0 0 200 200">
      <circle r="80" cx="100" cy="100" fill="none" stroke-width="12" stroke="#ccc"/>
      <circle r="80" cx="100" cy="100" fill="none" stroke-width="12" stroke="orangered"
              stroke-linecap="round" stroke-dasharray="226 502.4"
              stroke-dashoffset="-45" />
      <text x="100" y="125" font-family="Arial" font-size="70" 
            text-anchor="middle" fill="#444">
        50
      </text>
    </svg>
  </body>
</html>

 

Обратите внимание, что текст вставляется не внутрь тега circle, а под ним, иначе он не отобразится.

 

 

Теперь можно добавить элементы оформления: белый край у линии и тень.
 

<html>
  <head>
    <style>
      svg {
        width: 200px;
        height: 200px;
      }
    </style>
  </head>

  <body>
    <svg viewbox="0 0 200 200">
      <defs>
        <filter id="blurFilter" y="-5" height="40">
          <feGaussianBlur in="SourceGraphic" stdDeviation="3" y="-"/>
        </filter>
      </defs>
      <circle r="80" cx="95" cy="110"
              fill="none" stroke-width="12"
              stroke="#e0e0e0" filter="url(#blurFilter)">
      </circle>
      <circle r="80" cx="100" cy="100"
              fill="none" stroke-width="12"
              stroke="#ccc" stroke-dasharray="502,4 502,4"
              stroke-linecap="round">
      </circle>
      <circle r="24" cx="172" cy="123"
              fill="#e0e0e0" stroke-width="0"
              stroke="#e0e0e0" filter="url(#blurFilter)">
      </circle>
      <circle r="80" cx="100" cy="100" fill="none" 
              stroke-width="12" stroke="#F3F5F6" stroke-dashoffset="-42"
              stroke-dasharray="10.5 502.4" stroke-linecap="round">
      </circle>
      <circle r="80" cx="100" cy="100" fill="none" 
              stroke-width="12" stroke="orangered" stroke-linecap="round"
              stroke-dashoffset="-45" stroke-dasharray="4.5 502.4">
      </circle>
      <text x="100" y="125" font-family="Arial" font-size="70" 
            text-anchor="middle" fill="#444">
        1
      </text>
      <g>
         <circle r="24" cx="175" cy="120" fill="#F3F5F6" 
                 stroke-width="0" stroke="#F3F5F6"/>
    <circle r="20" cx="175" cy="120" fill="orangered" 
               stroke-width="0" stroke="orangered"/>
    <text x="175" y="126" font-family="Arial" font-size="18"
          text-anchor="middle" fill="#fff">
      %
    </text>
  </g>
</svg>
  </body>
</html>

 

 

Ссылка на "живой" пример.