BreakdownStatusChart

by tnhu

HTML

<svg viewBox="-1 -1 2 2">
  <defs>    
    <mask id="mask">
      <circle cx="0" cy="0" r="50%" fill="white" />
      <circle cx="0" cy="0" r="35%" fill="black" />
    </mask>
  </defs>

  <image x="-1" y="-1" width="50%" height="50%" xlink:href="https://localhost:8000/img/deployments/icon-deployments-running.svg" transform="translate(.5,.5)"/>
  
</svg><img src="https://i.imgur.com/0POBFcV.png" width="100px" height="100px"/>
<br/>
<img src="https://i.imgur.com/0POBFcV.png" width="100px" height="100px"/>

CSS

body {
  width: 100%;
  height: 100%;
  background: #dfdfdf;
}

svg {
  height: 90px; // the contents will scale to fit because of viewBox
  width: 90px;
  display: inline-block;
  margin: 5px;
}

JavaScript

const svgEl = document.querySelector('svg');
const slices = [
  { percent: 0.20, color: 'transparent' },
  { percent: 0.25, color: 'red' },
  { percent: 0.15, color: 'green' },
  { percent: 0.40, color: 'blue' },
];
let cumulativePercent = 0.30/2;

function getCoordinatesForPercent(percent) {
  const x = Math.cos(2 * Math.PI * percent);
  const y = Math.sin(2 * Math.PI * percent);
  return [x, y];
}

slices.forEach(slice => {
  // destructuring assignment sets the two variables at once
  const [startX, startY] = getCoordinatesForPercent(cumulativePercent);
  
  // each slice starts where the last slice ended, so keep a cumulative percent
  cumulativePercent += slice.percent;
  
  const [endX, endY] = getCoordinatesForPercent(cumulativePercent);

  // if the slice is more than 50%, take the large arc (the long way around)
  const largeArcFlag = slice.percent > .5 ? 1 : 0;

	// create an array and join it just for code readability
  const pathData = [
    `M ${startX} ${startY}`, // Move
    `A 1 1 0 ${largeArcFlag} 1 ${endX} ${endY}`, // Arc
    `L 0 0` // Line
  ].join(' ');

  // create a <path> and append it to the <svg> element
  const pathEl = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  pathEl.setAttribute('d', pathData);
  pathEl.setAttribute('fill', slice.color);
  pathEl.setAttribute('mask', 'url(#mask)')
  svgEl.append(pathEl);
});