<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();
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.