Как сверстать круговой график на svg

133
10 января 2020, 06:30

Есть такой вот макет

Нужно чтобы разноцветные дуги можно было выставит в зависимости от значений. Как сверстать такой график на svg?

То есть должен получиться вот такой вот график в итоге с значениями слева

Answer 1

Вот d3.js версия, если угодно. Используем генератор примитивов d3.arc()

он на вход кушает объект-описание дуги, а на выходе дает готовый <path>

let data = { 
  innerRadius: 10, 
  outerRadius: 20, 
  startAngle: Math.PI/4, 
  endAngle: Math.PI*3/2, 
  cornerRadius: 201 
} 
 
let d = d3.arc().cornerRadius(22)(data) 
 
d3.select('svg').append('path') 
  .attr('d', d).attr('fill', '#0ad01f')
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 
<body style="margin:0;overflow:hidden"> 
  <svg viewBox="-30 -20 75 75" height="100vh"></svg> 
<body>

Анимация диаграммы:

let data = [ 
  [1, '#0578e9'],  
  [2, '#f278bb'],  
  [3, '#f9b349'],  
  [4, '#3eb060'] 
].map((d, i) => ({ 
  index: i,  
  color: d[1], 
  k: d[0] 
})); 
 
let arc = d3.arc().cornerRadius(10).startAngle(0); 
let svg = d3.select('svg'); 
let size = Math.PI*3/2; 
arcs(true); 
requestAnimationFrame(draw); 
 
function draw(dt) { 
  arcs(false, dt); 
  requestAnimationFrame(draw); 
} 
 
function arcs(isBg, dt) { 
  let selection = svg.selectAll('path.'+ (isBg ? 'bg' : 'arc')) 
  selection = selection.data(data).enter().append('path').merge(selection); 
  selection.classed(isBg ? 'bg' : 'arc', true) 
    .attr('fill', d => isBg ? '#ccc' : d.color) 
    .attr('d', d => arc({ 
      innerRadius: 20 + d.index*15 + (d.index?0:3), 
      outerRadius: 20 + d.index*15 + 8, 
      endAngle: isBg ? size : (d.k*dt/300%100)*size/100 
    })) 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 
<body style="margin:0;overflow:hidden"> 
  <svg viewBox="-75 -75 150 150" height="100vh"></svg> 
<body>

Вариант, в котором видно как инициализировать диаграмму внешними данными

chart([  
  [20, '#0578e9', "142 000 м²"],  
  [40, '#f278bb', "82 000 м²"],  
  [60, '#f9b349', "60 000 м²"],  
  [80, '#3eb060', "20 000 м²"] 
].map((d, i) => ({ 
  index: i,  
  color: d[1], 
  value: d[0], 
  text: d[2] 
}))); 
 
function chart(data){ 
  let arc = d3.arc().cornerRadius(10).startAngle(0); 
  let svg = d3.select('svg'); 
  let size = Math.PI*3/2; 
  arcs(true); 
  arcs(false); 
  svg.selectAll('text').data(data).enter().append('text') 
     .text( d => d.text) 
     .style('font-size', 10) 
     .style('text-anchor', 'end') 
     .style('font-family', 'arial') 
     .attr('x', -10) 
     .attr('y', d => d.index*14-65) 
 
  function arcs(isBg) { 
    let selection = svg.selectAll('path.'+ (isBg ? 'bg' : 'arc')) 
    selection = selection.data(data).enter().append('path').merge(selection); 
    selection.classed(isBg ? 'bg' : 'arc', true) 
      .attr('fill', d => isBg ? '#ccc' : d.color) 
      .attr('d', d => arc({ 
        innerRadius: 20 + d.index*15 + (d.index?0:3), 
        outerRadius: 20 + d.index*15 + 8, 
        endAngle: isBg ? size : d.value*size/100 
      })) 
  } 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> 
<body style="margin:0;overflow:hidden"> 
  <svg viewBox="-75 -75 150 150" height="100vh"></svg> 
<body>

READ ALSO
Сверстать рамку с градиентом

Сверстать рамку с градиентом

Есть такой макет

140
Не выводится изменённая переменная

Не выводится изменённая переменная

есть DIV элемент у которого есть атрибут onclick вызывающий эту функцию

129
Ошибка в коде: не видит переменную(вроде)

Ошибка в коде: не видит переменную(вроде)

В предпоследней строчке("moneyDivinnerHTML = moneyNum;") браузерный редактор выдаёт ошибку "Uncaught ReferenceError: moneyDiv is not defined at HTMLDivElement

197
Не работает get-запрос

Не работает get-запрос

Необходимо получить json данные с сайта но с помощью $get получить данные не получается , по причине отсутствия заголовка CORS Хотя и получается...

173