Как нарисовать кольцевую диаграмму с закругленными углами и разными градиентами и тенями в каждом сегменте

Мне необходимо реализовать кольцевую диаграмму как на изображении ниже:

введите сюда описание изображения

Возникает несколько проблем:

  1. Каждый сегмент окрашен в свой градиент
  2. Сегменты имеют закругленные края
  3. Каждый сегмент может быть использован в дальнейшем, как ссылка

Конечно можно решить эти вопросы в векторном редакторе, создав для каждого сегмента свой path, но такое решение трудоемко и нужно будет каждый раз перерисовывать, если количество сегментов будет изменено и/или будет изменен их размер.

Стандартное решение, разбить окружность на сектора с помощью stroke-dasharray, не подойдет, так как все сегменты при этом решении, будут окрашены в один цвет;

Вот примерный код, но он не решает проблемы:

<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400" style="border:1px solid" >  

<circle id="s2"  cx="200" cy="200" r="160"  fill="none"  stroke="#FAE094"  stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5" />
 
<polyline points="200,0 200,400" fill="none" stroke="black" />
  <polyline points="0,200 400,200" fill="none" stroke="black" />

</svg>    

  • Как сделать сегменты разной длины?
  • Как закрасить их разными градиентами?
  • Как сделать закругленные края для каждого сегмента.

Примечание.

Атрибут stroke-lineCap="round" не подойдет, так как полностью закруглит края, а нужно, как на рисунке, совсем немного закруглить.


Ответы (1 шт):

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

Чтобы каждый сегмент был самостоятельным для принятия своего градиента и в последствии мог бы быть использован, как отдельная ссылка, вместо одной окружности будем использовать четыре окружности, так как на диаграмме 4 сектора.

На каждой окружности будет выводиться только один сектор, а через пробелы будет видна вторая окружность со своим одним сектором и т.д.

#1. Пример окружности с одним сектором:

<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400" style="border:1px solid" >  

<circle id="s2" transform="rotate(-120 200 200)" cx="200" cy="200" r="160"  fill="none"  stroke="#FAE094"  stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" />

<polyline points="200,0 200,400" fill="none" stroke="black" />
  <polyline points="0,200 400,200" fill="none" stroke="black" />

</svg>    

#2. Добавляем остальные окружности со своими секторами

<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400" style="border:1px solid" >  
    
<circle id="s1" transform="rotate(-120 200 200)" cx="200" cy="200" r="160"  fill="none"  stroke="#FAE094"  stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" />
 
 <circle id="s2" transform="rotate(-58 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#FCF0D0" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" /> 
 
 <circle id="s3" transform="rotate(5 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="335, 670" /> 

    <circle id="s4" transform="rotate(137 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="296, 695" />


<polyline points="200,0 200,400" fill="none" stroke="black" />
  <polyline points="0,200 400,200" fill="none" stroke="black" />

</svg>    

#3. Делаем закругленные уголки у секторов

Для этого используем SVG filter:

<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" 
              values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>

<style>
circle{ 
filter:url(#goo); 
}
</style>
<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400" style="border:1px solid" >  
<defs>
<filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
</defs> 
<circle id="s1" transform="rotate(-120 200 200)" cx="200" cy="200" r="160"  fill="none"  stroke="#FAE094"  stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" />
 
 <circle id="s2" transform="rotate(-58 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#FCF0D0" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" /> 
 
 <circle id="s3" transform="rotate(5 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="335, 670" /> 

    <circle id="s4" transform="rotate(137 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="296, 695" />
</svg>    

#4. Добавляем радиальные градиенты

Каждому сектору свой градиент:

circle{ 
filter:url(#goo); 
}
#s1 {
stroke:url(#rg1);
}
#s2 {
stroke:url(#rg2);
} 
#s3 {
stroke:url(#rg3);
}
#s4 {
stroke:url(#rg4);
}
<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400" >  
    <defs>
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    <radialGradient id="rg1" r="1" fx="0.6" fy="0.5">
              <stop offset="40%" stop-color="#F6BD4A"></stop>
              <stop offset="50%" stop-color="#F6DFB2"></stop>
               <stop offset="70%" stop-color="white"></stop>
                <stop offset="90%" stop-color="#F6AC17"></stop>
              
            </radialGradient>
    
    <radialGradient id="rg2" r="1" fx="0.4" fy="0.5">
              <stop offset="40%" stop-color="#F6BD4A"></stop>
              <stop offset="50%" stop-color="#F6DFB2"></stop>
               <stop offset="70%" stop-color="white"></stop>
                <stop offset="90%" stop-color="#F6AC17"></stop>
    </radialGradient>           
     <radialGradient id="rg3" r="1" fx="0.5" fy="0.5">
              <stop offset="40%" stop-color="#DCDCDC"></stop>
              <stop offset="50%" stop-color="#FFFFFF"></stop>
               <stop offset="60%" stop-color="#CDCDCD"></stop>
                <stop offset="90%" stop-color="#CDCDCD"></stop>
              
            </radialGradient>                
            
    <radialGradient id="rg4" r="1" fx="0.5" fy="0.5">
              <stop offset="40%" stop-color="#DCDCDC"></stop>
              <stop offset="50%" stop-color="#F3F3F3"></stop>
               <stop offset="60%" stop-color="#B8B8B8"></stop>
                <stop offset="90%" stop-color="#B8B8B8"></stop>
              
            </radialGradient>       
    
    </defs>  

<circle id="s1" transform="rotate(-120 200 200)" cx="200" cy="200" r="160"  fill="none"    stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" />
 
 <circle id="s2" transform="rotate(-58 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#FCF0D0" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" /> 
  
  <circle id="s3" transform="rotate(5 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="335, 670" /> 
  
  <circle id="s4" transform="rotate(137 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="296, 695" />
</svg>

UPDATE

<style>
circle{ 
filter:url(#goo); 
}
#s1 {
stroke:url(#rg1);
}
#s2 {
stroke:url(#rg2);
} 
#s3 {
stroke:url(#rg3);
}
#s4 {
stroke:url(#rg4);
}
</style>
<svg  xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink"
         width="400" height="400" viewBox="0 0 400 400"  >  
    <defs>
        <filter id="goo"><feGaussianBlur in="SourceGraphic" stdDeviation="8" result="blur" />    
            <feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 19 -9" result="goo" />
            <feComposite in="SourceGraphic" in2="goo" operator="atop"/>
        </filter>
    <radialGradient id="rg1" r="1" fx="0.6" fy="0.5">
              <stop offset="40%" stop-color="#F6BD4A"></stop>
              <stop offset="50%" stop-color="#F6DFB2"></stop>
               <stop offset="70%" stop-color="white"></stop>
                <stop offset="90%" stop-color="#F6AC17"></stop>
              
            </radialGradient>
    
    <radialGradient id="rg2" r="1" fx="0.4" fy="0.5">
              <stop offset="40%" stop-color="#F6BD4A"></stop>
              <stop offset="50%" stop-color="#F6DFB2"></stop>
               <stop offset="70%" stop-color="white"></stop>
                <stop offset="90%" stop-color="#F6AC17"></stop>
    </radialGradient>           
     <radialGradient id="rg3" r="1" fx="0.5" fy="0.5">
              <stop offset="40%" stop-color="#DCDCDC"></stop>
              <stop offset="50%" stop-color="#FFFFFF"></stop>
               <stop offset="60%" stop-color="#CDCDCD"></stop>
                <stop offset="90%" stop-color="#CDCDCD"></stop>
              
            </radialGradient>                
            
    <radialGradient id="rg4" r="1" fx="0.5" fy="0.5">
              <stop offset="40%" stop-color="#DCDCDC"></stop>
              <stop offset="50%" stop-color="#F3F3F3"></stop>
               <stop offset="60%" stop-color="#B8B8B8"></stop>
                <stop offset="90%" stop-color="#B8B8B8"></stop>
              
            </radialGradient>       
    
    </defs>  
 <a href="https://ru.stackoverflow.com/questions/tagged/svg">
  <title>Вопросы с меткой [SVG]</title>
<circle id="s1" transform="rotate(-120 200 200)" cx="200" cy="200" r="160"  fill="none"    stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" />
 </a> 
 <a href="https://ru.stackoverflow.com/questions/tagged/css">
  <title>Вопросы с меткой [CSS]</title>
 <circle id="s2" transform="rotate(-58 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#FCF0D0" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="167.5, 837.7" /> 
 </a>  
  <a href="https://ru.stackoverflow.com/questions/tagged/javascript">
  <title>Вопросы с меткой [Javascript]</title>
  <circle id="s3" transform="rotate(5 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="335, 670" /> 
  </a> 
 <a href="https://ru.stackoverflow.com/questions/tagged/python">
  <title>Вопросы с меткой [python]</title> 
  <circle id="s4" transform="rotate(137 200 200)" cx="200" cy="200" r="160"  fill="none" stroke="#C4C4C4" stroke-width="50" stroke-dashoffset="1005.2" stroke-dasharray="296, 695" />
</svg>  
 </a>  

#5. Вариант с всплывающими подсказками при наведении и переходом по ссылке при клике

→ Ссылка