<svg class="svg-pipe-chart" viewBox="0 0 100 100" width="200" height="200">
  <defs>
    <pattern
       id="pie-pattern-empty" 
       width="5%" height="5%" 
       viewBox="0 0 100 100" 
       patternTransform="rotate(-30)">
      <rect width="100" height="50" fill="crimson" />
    </pattern>
    
    <pattern
       id="pie-pattern-1" 
       width="10%" height="10%" 
       viewBox="0 0 100 100" 
       patternTransform="rotate(-45)">
      <rect width="100" height="50" fill="#1e8dcc" />
    </pattern>
    
    <pattern
       id="pie-pattern-2" 
       width="10%" height="10%" 
       viewBox="0 0 100 100" 
       patternTransform="rotate(45)">
      <rect width="100" height="50" fill="#3f8a6a" />
    </pattern>
    
    <clipPath id="pie-clip">
      <circle cx="50%" cy="50%" r="50%"/>
    </clipPath>
    
    <clipPath id="pie-clip-back">
      <path d="m100,100H0V0h100v100Zm5-50c0-30.38-24.62-55-55-55S-5,19.62-5,50s24.62,55,55,55,55-24.62,55-55"/>
    </clipPath>
  </defs>
  
  <g clip-path="url(#pie-clip)" transform="rotate(-90 50 50)">
    <circle
      class="svg-pie-chart__part-2"
      cx="50%" cy="50%" r="50%"
      stroke="#3f8a6a"
      stroke-width="100%"
      stroke-dasharray="314.1593"
      stroke-dashoffset="0"
      stroke-opacity="0.75"
      fill="none"/>
    
    <circle 
      class="svg-pie-chart__part-1"
      cx="50%" cy="50%" r="50%"
      fill="none"
      stroke="#1e8dcc"
      stroke-width="100%"
      stroke-dasharray="314.1593"
      stroke-dashoffset="0"/>
    
    <circle
      class="svg-pie-chart__part-empty"
      cx="50%" cy="50%" r="50%"
      stroke="url(#pie-pattern-empty)"
      stroke-width="100%"
      stroke-dasharray="314.1593"
      stroke-dashoffset="0"
      fill="none"/>
  </g>
  
  <g clip-path="url(#pie-clip-back)">
    <rect x="0" y="0" width="50" height="50" fill="url(#pie-pattern-1)" />
    <rect x="0" y="50" width="50" height="50" fill="url(#pie-pattern-1)" transform="rotate(-90 25 75)" />
    
    <rect x="50" y="0" width="50" height="50" fill="url(#pie-pattern-2)" />
    <rect x="50" y="50" width="50" height="50" fill="url(#pie-pattern-2)" transform="rotate(90 75 75)" />
  </g>
</svg>

<div class="controls">
  <input class="controls__part-1" type="range" value="45" min="0" max="100" step="1">
  <input class="controls__part-2" type="range" value="45" min="0" max="100" step="1">
</div>
body {
  background:
    linear-gradient(to right, #0001 1px, transparent 1px) 0 0 / 8px 8px,
    linear-gradient(to bottom, #0001 1px, transparent 1px) 0 0 / 8px 8px;
  display: grid;
  grid-template-columns: 1fr 1fr;
}
const lerp = (a, b, t) => a * (1 - t) + b * t;

const diameter = 100;
const overlap = Math.PI * diameter * 0.01;

const part1 = document.querySelector('.svg-pie-chart__part-1');
const inputPart1 = document.querySelector('.controls__part-1');

const part2 = document.querySelector('.svg-pie-chart__part-2');
const inputPart2 = document.querySelector('.controls__part-2');

const partEmpty = document.querySelector('.svg-pie-chart__part-empty');

const partValues = {
  part1: Number(inputPart1.value),
  part2: Number(inputPart2.value),
  empty: Math.max(0, 100 - (Number(inputPart1.value) + Number(inputPart2.value)))
};

inputPart1.addEventListener('input', (event) => {
  partValues.part1 = Number(event.target.value);

  const total = partValues.part1 + partValues.part2;
  
  if (total > 100) {
    partValues.part2 = Math.max(0, partValues.part2 - (total - 100));
    partValues.empty = 0;
    inputPart2.value = partValues.part2;
  }

  update();
});

inputPart2.addEventListener('input', (event) => {
  partValues.part2 = Number(event.target.value);

  const total = partValues.part1 + partValues.part2;

  if (total > 100) {
    partValues.part1 = Math.max(0, partValues.part1 - (total - 100));
    partValues.empty = 0;
    inputPart1.value = partValues.part1;
  }

  update();
});

function update() {
  let t = partValues.part1 / 100;
  let fill = Math.PI * diameter * t;
  let offset = 0;
  part1.setAttribute('stroke-dasharray', `${fill} ${Math.PI * diameter}`);
  part1.setAttribute('stroke-dashoffset', offset);

  t = partValues.part2 / 100;
  fill = Math.PI * diameter * t + overlap;
  offset -= Math.PI * diameter * inputPart1.value / 100 - overlap;
  part2.setAttribute('stroke-dasharray', `${fill} ${Math.PI * diameter}`);
  part2.setAttribute('stroke-dashoffset', offset);

  partValues.empty = Math.max(0, 100 - (partValues.part1 + partValues.part2));
  t = partValues.empty / 100;
  fill = Math.PI * diameter * t;
  offset -= Math.PI * diameter * partValues.part2 / 100 + overlap;
  partEmpty.setAttribute('stroke-dasharray', `${fill} ${Math.PI * diameter}`);
  partEmpty.setAttribute('stroke-dashoffset', offset);
}

update();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.