自定义圆环图
Customizing Donut chart
我正在尝试制作圆环图
我想要一个类似于下图的设计,其中值显示在彩色饼图之间
import DonutChart from 'react-d3-donut';
let data = [{
count: 20 ,
color: "red" ,
name: 'My name'
},{
count:30,
color:"green",
name:"yeys"
},{
count:20,
color:"orange",
name:"yeys"
}]
<DonutChart
innerRadius={90}
outerRadius={100}
transition={true}
svgClass="example1"
pieClass="pie1"
displayTooltip={true}
strokeWidth={3}
data={data} />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
这是一个带有 D3 的简单圆环图:
const data = [
{value: 20, text: 'First', color: 'red'},
{value: 30, text: 'Second', color: 'green'},
{value: 60, text: 'Third', color: 'blue'},
];
const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));
const margin = 10;
const arcWidth = 30;
const radius = Math.min(width/2 - margin, height/2 - margin) - arcWidth / 2;
const center = {x: width / 2, y: height / 2};
let anglePos = 0;
const angleOffset = 0.025;
const sum = data.reduce((s, {value}) => s + value, 0);
data.forEach(({value, text, color}, index) => {
const angle = Math.PI * 2 * value / sum;
const start = {
x: center.x + radius * Math.sin(anglePos + angleOffset),
y: center.y + radius * -Math.cos(anglePos + angleOffset),
};
anglePos += angle;
const end = {
x: center.x + radius * Math.sin(anglePos - angleOffset),
y: center.y + radius * -Math.cos(anglePos -angleOffset),
};
const flags = value / sum >= 0.5 ? '1 1 1' : '0 0 1';
const pathId = `my-pie-chart-path-${index}`;
svg.append('path')
.attr('id', pathId)
.attr('d', `M ${start.x},${start.y} A ${radius},${radius} ${flags} ${end.x},${end.y}`)
.style('stroke', color)
.style('fill', 'none')
.style('stroke-width', arcWidth);
svg.append('text')
.attr('dy', 6)
.attr('text-anchor', 'middle')
.append('textPath')
.attr('startOffset', angle * radius / 2)
.attr('href', `#${pathId}`)
.text(text)
});
text {
font-family: Calibri;
font-size: 20px;
font-weight: bold;
fill: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="200" height="200"></svg>
带有文本背景的示例:
const data = [
{value: 20, text: 'First', color: 'red'},
{value: 30, text: 'Second', color: 'green'},
{value: 60, text: 'Third', color: 'blue'},
];
const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));
const margin = 10;
const arcWidth = 30;
const radius = Math.min(width/2 - margin, height/2 - margin) - arcWidth / 2;
const center = {x: width / 2, y: height / 2};
let anglePos = 0;
const angleOffset = 0.025;
const sum = data.reduce((s, {value}) => s + value, 0);
data.forEach(({value, text, color}, index) => {
const angle = Math.PI * 2 * value / sum;
const start = {
x: center.x + radius * Math.sin(anglePos + angleOffset),
y: center.y + radius * -Math.cos(anglePos + angleOffset),
};
anglePos += angle;
const end = {
x: center.x + radius * Math.sin(anglePos - angleOffset),
y: center.y + radius * -Math.cos(anglePos -angleOffset),
};
const flags = value / sum >= 0.5 ? '1 1 1' : '0 0 1';
const pathId = `my-pie-chart-path-${index}`;
svg.append('path')
.attr('id', pathId)
.attr('d', `M ${start.x},${start.y} A ${radius},${radius} ${flags} ${end.x},${end.y}`)
//.attr('stroke-linecap', 'round')
.style('stroke', color)
.style('fill', 'none')
.style('stroke-width', arcWidth);
const textBg = svg.append('path');
const textElement = svg.append('text')
.text(text)
.attr('dy', 6)
.attr('text-anchor', 'middle');
const textBox = textElement.node().getBBox();
textElement.text(null);
const bgAngle = Math.abs(textBox.x) / radius;
const midAngle = anglePos - angle / 2;
const endBgAngle = midAngle + bgAngle;
const startBg = {
x: center.x + radius * Math.sin(midAngle - bgAngle),
y: center.y + radius * -Math.cos(midAngle - bgAngle),
};
const endBg = {
x: center.x + radius * Math.sin(midAngle + bgAngle),
y: center.y + radius * -Math.cos(midAngle + bgAngle),
};
textBg.attr('d', `M ${startBg.x},${startBg.y} A ${radius},${radius} 0 0 1 ${endBg.x},${endBg.y}`)
.style('stroke', 'white')
.style('fill', 'none')
.attr('stroke-linecap', 'round')
.style('stroke-width', arcWidth * 0.6);
textElement.append('textPath')
.text(text)
.attr('startOffset', angle * radius / 2)
.attr('href', `#${pathId}`)
});
text {
font-family: Calibri;
font-size: 16px;
fill: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="200" height="200"></svg>
我正在尝试制作圆环图
我想要一个类似于下图的设计,其中值显示在彩色饼图之间
import DonutChart from 'react-d3-donut';
let data = [{
count: 20 ,
color: "red" ,
name: 'My name'
},{
count:30,
color:"green",
name:"yeys"
},{
count:20,
color:"orange",
name:"yeys"
}]
<DonutChart
innerRadius={90}
outerRadius={100}
transition={true}
svgClass="example1"
pieClass="pie1"
displayTooltip={true}
strokeWidth={3}
data={data} />
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
这是一个带有 D3 的简单圆环图:
const data = [
{value: 20, text: 'First', color: 'red'},
{value: 30, text: 'Second', color: 'green'},
{value: 60, text: 'Third', color: 'blue'},
];
const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));
const margin = 10;
const arcWidth = 30;
const radius = Math.min(width/2 - margin, height/2 - margin) - arcWidth / 2;
const center = {x: width / 2, y: height / 2};
let anglePos = 0;
const angleOffset = 0.025;
const sum = data.reduce((s, {value}) => s + value, 0);
data.forEach(({value, text, color}, index) => {
const angle = Math.PI * 2 * value / sum;
const start = {
x: center.x + radius * Math.sin(anglePos + angleOffset),
y: center.y + radius * -Math.cos(anglePos + angleOffset),
};
anglePos += angle;
const end = {
x: center.x + radius * Math.sin(anglePos - angleOffset),
y: center.y + radius * -Math.cos(anglePos -angleOffset),
};
const flags = value / sum >= 0.5 ? '1 1 1' : '0 0 1';
const pathId = `my-pie-chart-path-${index}`;
svg.append('path')
.attr('id', pathId)
.attr('d', `M ${start.x},${start.y} A ${radius},${radius} ${flags} ${end.x},${end.y}`)
.style('stroke', color)
.style('fill', 'none')
.style('stroke-width', arcWidth);
svg.append('text')
.attr('dy', 6)
.attr('text-anchor', 'middle')
.append('textPath')
.attr('startOffset', angle * radius / 2)
.attr('href', `#${pathId}`)
.text(text)
});
text {
font-family: Calibri;
font-size: 20px;
font-weight: bold;
fill: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="200" height="200"></svg>
带有文本背景的示例:
const data = [
{value: 20, text: 'First', color: 'red'},
{value: 30, text: 'Second', color: 'green'},
{value: 60, text: 'Third', color: 'blue'},
];
const svg = d3.select('svg');
const width = parseInt(svg.attr('width'));
const height = parseInt(svg.attr('height'));
const margin = 10;
const arcWidth = 30;
const radius = Math.min(width/2 - margin, height/2 - margin) - arcWidth / 2;
const center = {x: width / 2, y: height / 2};
let anglePos = 0;
const angleOffset = 0.025;
const sum = data.reduce((s, {value}) => s + value, 0);
data.forEach(({value, text, color}, index) => {
const angle = Math.PI * 2 * value / sum;
const start = {
x: center.x + radius * Math.sin(anglePos + angleOffset),
y: center.y + radius * -Math.cos(anglePos + angleOffset),
};
anglePos += angle;
const end = {
x: center.x + radius * Math.sin(anglePos - angleOffset),
y: center.y + radius * -Math.cos(anglePos -angleOffset),
};
const flags = value / sum >= 0.5 ? '1 1 1' : '0 0 1';
const pathId = `my-pie-chart-path-${index}`;
svg.append('path')
.attr('id', pathId)
.attr('d', `M ${start.x},${start.y} A ${radius},${radius} ${flags} ${end.x},${end.y}`)
//.attr('stroke-linecap', 'round')
.style('stroke', color)
.style('fill', 'none')
.style('stroke-width', arcWidth);
const textBg = svg.append('path');
const textElement = svg.append('text')
.text(text)
.attr('dy', 6)
.attr('text-anchor', 'middle');
const textBox = textElement.node().getBBox();
textElement.text(null);
const bgAngle = Math.abs(textBox.x) / radius;
const midAngle = anglePos - angle / 2;
const endBgAngle = midAngle + bgAngle;
const startBg = {
x: center.x + radius * Math.sin(midAngle - bgAngle),
y: center.y + radius * -Math.cos(midAngle - bgAngle),
};
const endBg = {
x: center.x + radius * Math.sin(midAngle + bgAngle),
y: center.y + radius * -Math.cos(midAngle + bgAngle),
};
textBg.attr('d', `M ${startBg.x},${startBg.y} A ${radius},${radius} 0 0 1 ${endBg.x},${endBg.y}`)
.style('stroke', 'white')
.style('fill', 'none')
.attr('stroke-linecap', 'round')
.style('stroke-width', arcWidth * 0.6);
textElement.append('textPath')
.text(text)
.attr('startOffset', angle * radius / 2)
.attr('href', `#${pathId}`)
});
text {
font-family: Calibri;
font-size: 16px;
fill: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<svg width="200" height="200"></svg>