Для создания разнообразных примеров прогрессбаров, лоадеров и других анимированных объетов, применение stroke-dashharray, stroke-dashoffset является основным способом.
В статье: Анимация рисования линии используется только изменение атрибута stroke-dashoffset от максимума до нуля.
Но если использовать комбинацию stroke-dasharray и stroke-dashoffset, то можно получить интереснейшие эффекты.
Форма прогрессбара неважна, она может быть любой,- или прямая линия или замкнутая фигура.
Главное это правильно указать максимальную длину контура.
Увеличение заполняющей полосы прогрессбара может быть реализовано двумя способами:
Полная длина окружности равна
C = 2 x PI x R или 2 x 3.14 x 50 = 314px
При stroke-dashoffset = “314” линия будет полностью скрыта
При stroke-dashoffset = “0” линия будет полностью видна
Изменяя значение Stroke-dashoffset от максимума до нуля получим эффект заполнения прогрессбара
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#D0D0D0" /> <!-- Путь заполнения линии прогрессбара --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="8"/> <circle cx="60" cy="60" r="50" transform="rotate(-90 60 60)" fill="none" stroke-dashoffset="314" stroke-dasharray="314" stroke="dodgerblue" stroke-width="8" > <!--Анимация изменение отступа линии stroke-dashoffset от 314 до 0 --> <animate attributeName="stroke-dashoffset" dur="4s" begin="svg1.click" values="314;0" /> </circle> <text id="count" x="50%" y="50%" fill="#717171" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
При stroke-dasharray=”0,314″ линия будет полностью скрыта, так как первый параметр, – это длина черты равна нулю, а второй параметр – пробел имеет максимальную длину
При stroke-dasharray=”314,0″ линия будет полностью показана, так как черта имеет максимальную длину, а пробел равен нулю.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#D0D0D0" /> <!-- Путь заполнения линии прогрессбара --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="8"/> <circle cx="60" cy="60" r="50" transform="rotate(-90 60 60)" fill="none" stroke-dashoffset="314" stroke-dasharray="0, 314" stroke="purple" stroke-width="8" > <!-- Анимация изменения длины черты stroke-dasharray от нуля до максимума 314 --> <animate attributeName="stroke-dasharray" dur="4s" begin="svg1.click" values="0,314;314,0" fill="freeze" /> </circle> <text id="count" x="50%" y="50%" fill="#622B80" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
На мой взгляд это интересная техника. Реализуется за счёт деления всей окружности на две равные части, которые изначально невидны. Как известно stroke-dasharray может иметь, как одну пару параметров: длина черты + длина пробела, так и несколько пар. Будем использовать две пары параметров stroke-dasharray
Если полная длина равна 314, то можно разделить всю окружность на две равные части
stroke-dasharray=”0,157 0,157″
По порядку: 0 – черта равна нулю, 157 – длина пробела. Вот таким образом скрывается одна половина окружности
Далее для второй половины окружности: 0 – черта равна нулю, 157 – длина пробела
При значении stroke-dasarray=”0,0 314,0″ линия покажется полностью, так как значение третьего параметра длины черты равно 314px, что соответствует полной длине окружности.
Анимируя изменение параметров stroke-dasarray, соответствующее невидимости линии до полной видимости values=”0,157 0,157;0,0,314,0″ получим анимацию заполнения прогрессбара из одной точки. Где в формуле values эти два состояния (видимой ; невидимой линии) разделены точкой с запятой.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#D0D0D0" /> <!-- Показывает путь заполнения --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="8"/> <!-- Линия, которая делится с помощью stroke-dasharray на две части --> <circle cx="60" cy="60" r="50" fill="none" stroke-dashoffset="-78.5" stroke-dasharray="0,157 0,157" stroke="orange" stroke-width="8" > <!-- Анимация заполнения из одной точки двумя линиями --> <animate attributeName="stroke-dasharray" dur="4s" begin="svg1.click" values="0,157 0,157;0,0,314,0" fill="freeze" /> </circle> <text id="count" x="50%" y="50%" fill="#E49400" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
В примере ниже использован октагон (восьмиугольник) Полная длина контура фигуры равна 330px
Также возможно сдвинуть начальную точку заполнения в любую сторону. Например для начальной точки слева сдвигаем на четверть с помощью
stroke-dashoffset=”-82.5″
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<svg id="svg1" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 120 120" version="1.1"> <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#D0D0D0" /> <!-- Показывает путь заполнения --> <path d="M60 6.4 98.1 22.1 113.9 60.3 98.1 98.4 60 114.2 21.9 98.4 6.1 60.3 21.9 22.1Z" fill="none" stroke="#E1E1E1" stroke-width="6"/> <path d="M60 6.4 98.1 22.1 113.9 60.3 98.1 98.4 60 114.2 21.9 98.4 6.1 60.3 21.9 22.1Z" fill="none" stroke-dashoffset="-82.5" stroke-dasharray="0,165 0,165" stroke="#E43673" stroke-width="6"> <!-- Анимация заполнения из одной точки двумя линиями --> <animate attributeName="stroke-dasharray" dur="4s" begin="svg1.click" values="0,165 0,165;0,0,330,0" fill="freeze" /> </path> <text id="count" x="50%" y="50%" fill="#C12D61" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
Заполнение прерывистой линией имеет некоторые нюансы. Так как назначив, допустим stroke-dasharray=”3.14, 3.14″ мы тем самым разбиваем круг на 50 равных частей.
И он оказывается полностью заполненным. Анимация сдвига (заполнения) с помощью stroke-dashoffset=”314;0″ вызовет только вращение.
Для реализации эффекта заполнения необходимо использовать другие техники. Например можно создать иллюзию заполнения круга прерывистой линией с помощью анимации маски.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#F3F3F3" /> <!-- Путь заполнения линии прогрессбара --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="12"/> <circle cx="60" cy="60" r="50" transform="rotate(-90 60 60)" fill="none" stroke-dashoffset="314" stroke-dasharray="3.14, 3.14" stroke="#A023FF" stroke-width="12" > <!-- Анимация вращения с помощью сдвига командой stroke-dashoffset --> <animate attributeName="stroke-dashoffset" dur="6s" begin="svg1.click" values="314;0" fill="freeze" /> </circle> <text id="count" x="50%" y="50%" fill="#622B80" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
Как сказано выше, предварительно заполняем круг прерывистой линией
stroke-dasharray=”3.14, 3.14″
Экранируем этот круг с помощью маски, в основе которой находится точно такой же круг.
Далее анимируем сдвиг маски, который обеспечивает открывание прерывистой линии, создавая иллюзию заполнения круга прерывистой линией.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <defs> <mask id="msk1"> <rect width="100%" height="100%" fill="white" /> <circle cx="60" cy="60" r="50" stroke= "black" fill="none" stroke-dashoffset="0" stroke-dasharray="314" stroke-width="14" > <!-- Анимация сдвига маски реализует открывание прерывистой линии --> <animate attributeName="stroke-dashoffset" dur="6s" begin="svg1.click" values="0;-314;" fill="freeze" /> </circle> </mask> </defs> <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#F3F3F3" /> <!-- Путь заполнения линии прогрессбара --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="12"/> <!-- Прерывистая линия заэкранирована маской mask="url(#msk1)" --> <circle cx="60" cy="60" r="50" mask="url(#msk1)" transform="rotate(-90 60 60)" fill="none" stroke-dashoffset="314" stroke-dasharray="3.14, 3.14" stroke="#62169D" stroke-width="12" /> <text id="count" x="50%" y="50%" fill="#622B80" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |
Использована техника заполнения двумя линиями из одной точки и прием экранирования маской прерывистой линией, как в примерах выше.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" viewBox="0 0 120 120" > <defs> <mask id="msk1"> <rect width="100%" height="100%" fill="white" /> <circle cx="60" cy="60" r="50" stroke= "black" fill="none" stroke-dashoffset="157" stroke-dasharray="157,0 157,0" stroke-width="14" > <!-- Анимация сдвига маски реализует открывание прерывистой линии --> <animate attributeName="stroke-dasharray" dur="4s" begin="svg1.click" values="157,0 157,0;0,314,0,0;" fill="freeze" /> </circle> </mask> </defs> <!-- Фон серого цвета --> <rect width="100%" height="100%" fill="#F3F3F3" /> <!-- Путь заполнения линии прогрессбара --> <circle cx="60" cy="60" r="50" fill="none" stroke="#E1E1E1" stroke-width="14"/> <!-- Прерывистая линия заэкранирована маской mask="url(#msk1)" --> <circle cx="60" cy="60" r="50" mask="url(#msk1)" transform="rotate(-90 60 60)" fill="none" stroke-dashoffset="314" stroke-dasharray="3.14, 3.14" stroke="#62169D" stroke-width="12" /> <text id="count" x="50%" y="50%" fill="#622B80" text-anchor="middle" dy="7" font-size="20">Click</text> </svg> |