Как создавать кольцевые диаграммы с помощью stroke-dashoffset и stroke-dasharray
У меня есть 3 кольцевые диаграммы SVG, на каждой диаграмме есть линия, созданная с помощью Stroke-Dasharray, в целом диаграммы составляют 100%.
Я бы хотел, чтобы каждый график начинался там, где заканчивается последний, чтобы первый график составлял от 0 до 60%. Я бы хотел, чтобы вторая диаграмма начиналась с 60% и доходила до 90%, а последняя диаграмма начиналась с 90% до 100%.
Я пытаюсь сделать это с помощью Stroke DashOffset, но не могу понять, как это работает.
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="green"
stroke-width="3"
stroke-dasharray="60 40"
stroke-dashoffset="25"></circle>
</svg>
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="red"
stroke-width="3"
stroke-dasharray="30 70"
stroke-dashoffset="60"></circle>
</svg>
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="grey"
stroke-width="3"
stroke-dasharray="10 90"
stroke-dashoffset="-"></circle>
</svg>
Свободный перевод вопроса Stroke-dashoffset, posiiton stroke-dasharray от участника @ttmt.
Ответы (2 шт):
Длина окружности - 2 * 3.14 * R. В данном случае длина окружности будет ~100, что очень удобно. stroke-dasharray - первое число - сколько идет dash, второе - сколько идет пропуск. stroke-dashoffset указывает откуда начинается график. методом подстановки, вычислил что идет он в обратную сторону, т.е. 25 - это x: 0, y: 1, а -25 это x: 0, y: -1, а -50 это x: -1, y: 0 (объясняю на примере тригонометрического круга, надеюсь понятно).
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="green"
stroke-width="3"
stroke-dasharray="60 40"
stroke-dashoffset="25"></circle>
</svg>
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="red"
stroke-width="3"
stroke-dasharray="30 70"
stroke-dashoffset="-35"></circle>
</svg>
<svg width="15%" height="15%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<circle class="donut"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="grey"
stroke-width="3"
stroke-dasharray="10 90"
stroke-dashoffset="-65"></circle>
</svg>
Окружность радиусом r="15,91 равна 2 * 3,1415 * 15,91 = 99,96 =~ 100.
stroke-dasharray="60 40", где
60 - dash (тире)
40 - gap (пробел)
Поскольку по умолчанию — Stroke-dashoffset = 0, круг будет начинаться под углом 0 градусов, то есть от положительного направления оси X.
Положительное значение Stroke-dashoffset = 25 смещает линию против часовой стрелки на четверть круга до пересечения с осью y. То есть зелёная линия теперь будет рисоваться из верхней точки пересечения с осью y.
<svg width="50%" height="50%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<!-- first chart is from 0-60% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="green"
stroke-width="3"
stroke-dasharray="60 40"
stroke-dashoffset="25">
</circle>
Отрицательное значение Stroke-dashoffset = -35 сдвигает второй красный круг по часовой стрелке к концу первой зеленой линии (25-60 = -35).
<svg width="50%" height="50%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<!-- first chart is from 0-60% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="green"
stroke-width="3"
stroke-dasharray="60 40"
stroke-dashoffset="25"></circle>
<!-- второй chart стартует от 60% и идёт до 90% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="red"
stroke-width="3"
stroke-dasharray="30 70"
stroke-dashoffset="-35"></circle>
</svg>
Отрицательное значение Stroke-dashoffset = -65 сдвигает третий оранжевый круг по часовой стрелке к концу второй красной линии (-35-30 = -65).
<svg width="50%" height="50%" viewBox="0 0 42 42" class="donut">
<circle class="donut-hole" cx="21" cy="21" r="15.91549430918954" fill="#fff"></circle>
<circle class="donut-ring" cx="21" cy="21" r="15.91549430918954" fill="transparent" stroke="#d2d3d4" stroke-width="3"></circle>
<!-- первый chart 0-60% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="green"
stroke-width="3"
stroke-dasharray="60 40"
stroke-dashoffset="25"></circle>
<!-- второй chart стартует от 60% и идёт до 90% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="red"
stroke-width="3"
stroke-dasharray="30 70"
stroke-dashoffset="-35"></circle>
<!-- третий (финальный) chart стартует от 90% до 100% -->
<circle class="donut-segment"
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="orange"
stroke-width="3"
stroke-dasharray="10 90"
stroke-dashoffset="-65"></circle>
Свободный перевод ответа от участника @Alexandr_TT.