Это то, что вы хотели?
Просто вычтите радиус круглых концевых колпачков (по одному на каждый конец) из длины тире.
Пока радиус круга не очень малкруглые колпачки должны аккуратно касаться друг друга.
const countries = [
{'percent': 10,colour: 'red'},
{'percent': 20,colour: 'blue'},
{'percent': 36,colour: 'yellow'},
{'percent': 34,colour: 'orange'}
];
const STROKE_WIDTH = 2.3;
const donutData = countries.map((country, index) => {
// Subtract the radius of the round cap, twice.
const dashLength = country.percent - STROKE_WIDTH;
return {
stroke: country.colour,
dashoffset: 25 - countries.slice(0, index).reduce((a, b) => a + b.percent, 0),
dashArray: [dashLength, 100 - dashLength]
}
});
const div = document.createElement('div');
div.innerHTML = '<svg id="donut" width="100%" height="100%" viewBox="3 3 36 36"></svg>';
document.body.appendChild(div);
document.querySelector('#donut').innerHTML= donutData.reduce((a, item) => {
return a +
`<circle
cx="21"
cy="21"
fill="transparent"
r="15.91549430918954"
stroke-width="${STROKE_WIDTH}"
stroke-linecap="round"
stroke="${item.stroke}"
stroke-dasharray="${item.dashArray[0]} ${item.dashArray[1]}"
stroke-dashoffset="${item.dashoffset}"></circle>
`;
}, '')
Обновление
Версия, которая несколько изящно обрабатывает короткие строки.
const countries = [
{'percent': 10, colour: 'red'},
{'percent': 20, colour: 'blue'},
{'percent': 36, colour: 'yellow'},
{'percent': 33, colour: 'orange'},
{'percent': 1, colour: 'green'},
];
const STROKE_WIDTH = 2.3;
const donutData = countries.map((country, index) => {
let dashLength, offsetAdjust, caps;
if (country.percent >= STROKE_WIDTH) {
// Subtract the radius of the round cap, twice.
dashLength = country.percent - STROKE_WIDTH;
offsetAdjust = STROKE_WIDTH / 2;
caps = "round";
} else {
dashLength = country.percent;
offsetAdjust = 0;
caps = "butt";
}
return {
stroke: country.colour,
dashoffset: 25 - countries.slice(0, index).reduce((a, b) => a + b.percent, 0) - offsetAdjust,
dashArray: [dashLength, 100 - dashLength],
caps: caps
}
});
const div = document.createElement('div');
div.innerHTML = '<svg id="donut" width="100%" height="100%" viewBox="3 3 36 36"></svg>';
document.body.appendChild(div);
document.querySelector('#donut').innerHTML= donutData.reduce((a, item) => {
return a +
`<circle
cx="21"
cy="21"
fill="transparent"
r="15.91549430918954"
stroke-width="${STROKE_WIDTH}"
stroke-linecap="${item.caps}"
stroke="${item.stroke}"
stroke-dasharray="${item.dashArray[0]} ${item.dashArray[1]}"
stroke-dashoffset="${item.dashoffset}"></circle>
`;
}, '')