Как создавать кольцевые диаграммы с помощью 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 шт):

Автор решения: Meth0d

Длина окружности - 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>

→ Ссылка
Автор решения: Alexandr_TT

Окружность радиусом 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.

→ Ссылка