Прогресс бар заполняется в обратном порядке
Т.е. когда stroke-dashoffset="565.48"
, то круг пустой, а когда stroke-dashoffset="0"
, то круг заполнен
Как инвертировать stroke-dashoffset
? В рамках svg файла.
<svg width="200" height="200" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg)">
<!-- Фоновый круг -->
<circle
r="90"
cx="100"
cy="100"
fill="transparent"
stroke="#e0e0e0"
stroke-width="16px"
stroke-dasharray="565.48px"
stroke-dashoffset="0">
</circle>
<!-- Круговой прогресс -->
<circle
id="procent_circle"
r="90"
cx="100"
cy="100"
stroke="#76e5b1"
stroke-width="16px"
stroke-dashoffset="565.48"
fill="transparent"
stroke-dasharray="565.48px">
</circle>
<!-- Текстовое поле для отображения процентов -->
<text
id="procent"
x="73px"
y="117px"
fill="#6bdba7"
font-size="52px"
font-weight="bold"
style="transform:rotate(90deg) translate(0px, -196px)">
58
</text>
</svg>
Ответы (4 шт):
Т.е. когда stroke-dashoffset="565.48", то круг пустой, а когда stroke-dashoffset="0", то круг заполнен
Всё правильно,- так и должно быть.
stroke-dashoffset Даже из названия атрибута понятно, что это отступ линии от начальной точки.
Если отступ максимален - 565.48, то строка пустая.
Если отступа нет - stroke-dashoffset="0"
строка заполнена полностью.
Так как circle
это окружность, кольцо, у которого нет начала и конца, то анимация с использованием stroke-dashoffset невозможна.
Просто отступы считать неоткуда.
Поэтому окружность нужно создавать с помощью path, либо для circle
использовать анимацию stroke-dasharray
<svg width="200" height="200" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg)">
<!-- Фоновый круг -->
<circle
r="90"
cx="100"
cy="100"
fill="transparent"
stroke="#e0e0e0"
stroke-width="16px" >
</circle>
<!-- Круговой прогресс -->
<circle
id="procent_circle"
r="90"
cx="100"
cy="100"
stroke="#76e5b1"
stroke-width="16px"
fill="transparent"
stroke-dasharray="0,565.48"
stroke-dashoffset="565.48">
<animate attributeName="stroke-dasharray" begin="0.2s" dur="2s" values="0, 565.48;565.48,0 " repeatCount="indefinite" />
</circle>
<!-- Текстовое поле для отображения процентов -->
<text
id="procent"
x="73px"
y="117px"
fill="#6bdba7"
font-size="52px"
font-weight="bold"
style="transform:rotate(90deg) translate(0px, -196px)">
58
</text>
</svg>
<animate attributeName="stroke-dasharray" begin="0.2s" dur="2s" values="0, 565.48;565.48,0 " repeatCount="indefinite" />
Секрет этой анимации в значении: values="0, 565.48;565.48,0 "
,где
0, 565.48 - черта установлена в нулевое значение, а пробел максимален
565.48,0 - черта максимальна, пробел равен нулю.
В результате анимации зеленая черта растет от нуля до максимума
Не знаю какой именно эффект должен быть, но если изменить "массив штрихов" на схему:
stroke-dasharray="0px 565.48px 565.48px"
И запустить анимацию, предложенную @Alexandr_TT, то вполне можно запустить прогресс-бар, меняя как раз stroke-dashoffset
от 0 до 565,48:
<animate attributeName="stroke-dashoffset" begin="0.2s" dur="2s" values="0;565.48" repeatCount="indefinite" />
<svg width="200" height="200" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" style="transform:rotate(-90deg)">
<!-- Фоновый круг -->
<circle
r="90"
cx="100"
cy="100"
fill="transparent"
stroke="#e0e0e0"
stroke-width="16px"
stroke-dasharray="0px 565.48px 565.48px"
stroke-dashoffset="0">
<animate attributeName="stroke-dashoffset" begin="0.2s" dur="2s" values="0;565.48" repeatCount="indefinite" />
</circle>
<!-- Круговой прогресс -->
<circle
id="procent_circle"
r="90"
cx="100"
cy="100"
stroke="#76e5b1"
stroke-width="16px"
stroke-dashoffset="565.48"
fill="transparent"
stroke-dasharray="565.48px">
</circle>
<!-- Текстовое поле для отображения процентов -->
<text
id="procent"
x="73px"
y="117px"
fill="#6bdba7"
font-size="52px"
font-weight="bold"
style="transform:rotate(90deg) translate(0px, -196px)">
58
</text>
</svg>
Когда
stroke-dashoffset="565.48"
, то круг пустой, а когдаstroke-dashoffset="0"
, то круг заполнен
В вашем вопросе уже есть ответ, можно просто уменьшать значение stroke-dashoffset
- т.е. 100% = 0, 0% = 565.48.
Формула: dash-array * (1 - percent / 100)
.
Ещё я упростил код SVG:
const input = document.querySelector('input[type="range"]');
const getPercent = () => {
const value = +input.value;
document.querySelectorAll('svg').forEach((svg) => {
const percent = svg.querySelector('.percent');
const text = svg.querySelector('.text');
const dashArray = +percent.getAttribute('stroke-dasharray');
percent.setAttribute('stroke-dashoffset', dashArray * (1 - value / 100));
text.textContent = value;
});
}
getPercent();
input.addEventListener('change', getPercent);
input.addEventListener('mousemove', getPercent);
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 2em;
width: 100%;
height: 100vh;
margin: 0;
}
.demo {
display: flex;
justify-content: center;
align-items: center;
gap: 1em;
}
svg {
width: 120px;
height: auto;
}
<div class="demo">
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<g stroke-width="16" fill="transparent" transform="rotate(-90 100 100)">
<circle cx="100" cy="100" r="90" stroke="#e0e0e0"/>
<circle class="percent" cx="100" cy="100" r="90" stroke="#76e5b1" stroke-dashoffset="565.48" stroke-dasharray="565.48"/>
</g>
<text class="text" x="100" y="113" fill="#6bdba7" font-size="52" font-weight="bold" dominant-baseline="top" text-anchor="middle">0</text>
</svg>
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<g stroke-width="16" fill="transparent" transform="rotate(-90 100 100) scale(1 -1) translate(0 -200)">
<circle cx="100" cy="100" r="90" stroke="#e0e0e0"/>
<circle class="percent" cx="100" cy="100" r="90" stroke="#76e5b1" stroke-dashoffset="565.48" stroke-dasharray="565.48"/>
</g>
<text class="text" x="100" y="113" fill="#6bdba7" font-size="52" font-weight="bold" dominant-baseline="top" text-anchor="middle">0</text>
</svg>
</div>
<input type="range" min="0" value="50" max="100" step="1" />
А ещё, я не правильно воспринял вопрос, и "развернул" ещё и сам прогресс, как это сделал Leonid.
Только для этого я использовал transform
.
Анимация stroke-dashoffset
Вариант ответа
Так как circle это окружность, кольцо, у которого нет начала и конца, то анимация с использованием stroke-dashoffset невозможна. Просто отступы считать неоткуда.
Поэтому окружность нужно создавать с помощью path, либо для circle использовать анимацию stroke-dasharray
Анимация с помощью stroke-dasharray рассмотрена в ответе раз и в ответе два
Для анимации stroke-dashoffset рисуем окружность в векторном редакторе.
Начинаем с верхней точки 1, откуда будет начинаться анимация заполнения круга:
- С помощью инструмента - Рисовать кривые Безье наносим 4 узловые точки по часовой стрелке.
- Меняем тип узловых точек на автоматически сглаженные
- Траектория круга будет автоматически нарисована. Далее сохраняем файл в формате *.svg и оптимизируем его с помощью SVGOMG
Круг, нарисованный с помощью path готов и его можно будет использовать в анимации stroke-dashoffset
<path transform="translate(0 -97)" stroke-dashofset="569.57" stroke-dasharray="569.57"
d="M100 106.9c42.4 0 90 35.2 90 90 0 58-33.1 90.3-90 90.3-43.1 0-90-31.4-90-90.4 0-55.2 47.6-90 90-90z"
style="stroke:#76e5b1; stroke-width:16; fill:none;stroke-linecap:butt">
Код с анимацией:
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 200 200" style="border:0px red solid">
<!-- Фоновый круг -->
<path transform="translate(0 -97)"
d="M100 106.9c42.4 0 90 35.2 90 90 0 58-33.1 90.3-90 90.3-43.1 0-90-31.4-90-90.4 0-55.2 47.6-90 90-90z" style="stroke:#e0e0e0; stroke-width:16; fill:none;stroke-linecap:butt">
</path>
<!-- Круговой прогресс -->
<path transform="translate(0 -97)" stroke-dashofset="569.57" stroke-dasharray="569.57"
d="M100 106.9c42.4 0 90 35.2 90 90 0 58-33.1 90.3-90 90.3-43.1 0-90-31.4-90-90.4 0-55.2 47.6-90 90-90z" style="stroke:#76e5b1; stroke-width:16; fill:none;stroke-linecap:butt">
<!-- Команда анимации -->
<animate attributeName="stroke-dashoffset" dur="4s" values="569.57;0" repeatCount="indefinite" />
</path>
<!-- Текстовое поле для отображения процентов -->
<text
id="procent"
x="73px"
y="117px"
fill="#6bdba7"
font-size="52px"
font-weight="bold"
>
58
</text>
</svg>
Секрет анимации в значении - values="569.57;0", где
stroke-dashoffset - отступ от начала линии изменяется от максимума до нуля, а это значит, что линия будет увеличиваться от нуля до полного заполнения.