<div id="app">
<input type="range" v-model="show" min="1" :max="chartData.length">
<div>{{show}}</div>
<input type="range" v-model="gap" min="0" max="10">
<svg viewBox="-100 -100 200 200" width="200" xmlns="http://www.w3.org/2000/svg" overflow="visible">
<g v-for="(path, index) in paths" :key="index" class="pie">
<path :d="path.d"></path>
<text :x="path.cx" :y="path.cy" text-anchor="middle" dominant-baseline="middle">{{chartData[index].text}}</text>
</g>
</svg>
</div>
body {
color: #fff;
background-color: #222;
font-family: monospace;
}
svg, input {
display: block;
}
.pie path {
fill: #2d2d2d;
stroke: #f8e5ad;
}
.pie text {
fill: #fff;
}
.pie:hover path {
fill: #f8e5ad;
stroke: #f8e5ad;
}
.pie:hover text {
fill: #2d2d2d;
}
new Vue({
el: '#app',
data: {
show: 5,
gap: 5,
from: -Math.PI / 2,
outerRadius: 100,
innerRadius: 30,
chartData: [
{ text: 'text_1' },
{ text: 'text_2' },
{ text: 'text_3' },
{ text: 'text_4' },
{ text: 'text_5' },
{ text: 'text_6' },
{ text: 'text_7' },
{ text: 'text_8' },
],
},
computed: {
paths() {
const from = this.from;
const n = this.show;
const step = 2 * Math.PI / n;
return this.chartData.slice(0, n).map((_, i) => {
return pie(from + step * i, step, this.outerRadius, this.innerRadius, this.gap);
});
}
}
})
function pie(from, angle, outerRadius, innerRadius, gap = 0) {
const or = outerRadius;
const ir = innerRadius;
let d;
if (angle > Math.PI) {
const x0 = or * Math.cos(from);
const y0 = or * Math.sin(from);
d = `M ${x0} ${y0} `;
const x1 = or * Math.cos(from + Math.PI);
const y1 = or * Math.sin(from + Math.PI);
d += `A ${or} ${or} 0 0 1 ${x1} ${y1} `;
d += `A ${or} ${or} 0 0 1 ${x0} ${y0} `;
const x2 = ir * Math.cos(from);
const y2 = ir * Math.sin(from);
d += `M ${x2} ${y2} `;
const x4 = ir * Math.cos(from + Math.PI);
const y4 = ir * Math.sin(from + Math.PI);
d += `A ${ir} ${ir} 0 0 0 ${x4} ${y4} `;
d += `A ${ir} ${ir} 0 0 0 ${x2} ${y2} Z`;
}
else {
const og = Math.asin(gap / 2 / outerRadius);
const ig = Math.asin(gap / 2 / innerRadius);
const x0 = or * Math.cos(from + og);
const y0 = or * Math.sin(from + og);
d = `M ${x0} ${y0} `;
const x2 = or * Math.cos(from + angle - og);
const y2 = or * Math.sin(from + angle - og);
d += `A ${or} ${or} 0 0 1 ${x2} ${y2} `;
const x3 = ir * Math.cos(from + angle - ig);
const y3 = ir * Math.sin(from + angle - ig);
d += `L ${x3} ${y3} `;
const x4 = ir * Math.cos(from + ig);
const y4 = ir * Math.sin(from + ig);
d += `A ${ir} ${ir} 0 0 0 ${x4} ${y4} `;
d += `L ${x0} ${y0} Z`;
}
const mid = from + angle / 2;
return {
d,
cx: (or + ir) * 0.5 * Math.cos(mid),
cy: (or + ir) * 0.5 * Math.sin(mid),
};
}
This Pen doesn't use any external CSS resources.