我正在尝试用 d3 库表示饼图。 我尝试制作饼图,但在用箭头围绕饼图绘制线条时遇到问题。
const data = [10, 10, 10, 10, 10, 10];
import React, { useEffect, useRef } from "react";
import * as d3 from "d3";
const PieChart = ({ data }) => {
const svgRef = useRef();
useEffect(() => {
createWheel();
}, [data]);
const createWheel = () => {
const width = 200;
const height = 200;
const outerRadius = 100;
const innerRadius = 0;
const borderWidth = 1;
const spaceBetweenSlices = 10;
const arrowSize = 30;
const padding = 20;
const svg = d3
.select(svgRef.current)
.attr("width", width + padding * 2)
.attr("height", height + padding * 2)
.append("g")
.attr(
"transform",
`translate(${width / 2 + padding},${height / 2 + padding})`
);
const pie = d3.pie();
const pieData = pie(data);
const arc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius);
const arcs = svg
.selectAll("arc")
.data(pieData)
.enter()
.append("g")
.attr("class", "arc");
arcs
.append("path")
.attr("d", arc)
.attr("fill", (d, i) => d3.schemeCategory10[i]);
const borderArc = d3
.arc()
.innerRadius(outerRadius + spaceBetweenSlices)
.outerRadius(outerRadius + borderWidth + spaceBetweenSlices);
arcs
.append("path")
.attr("d", borderArc)
.attr("fill", "none")
.attr("stroke", (d, i) => d3.schemeCategory10[i])
.attr("stroke-width", borderWidth);
// Add greater-than signs at the end of each border
arcs
.append("text")
.attr("x", (d) => borderArc.centroid(d)[0])
.attr("y", (d) => borderArc.centroid(d)[1])
.attr("dy", "0.35em")
.attr("text-anchor", "middle")
.attr("font-size", arrowSize)
.attr("fill", (d, i) => d3.schemeCategory10[i])
.text(">");
};
return <svg ref={svgRef}></svg>;
};
export default PieChart;
通过调整 SVG 容器内饼图的位置,向 SVG 元素添加填充。
在每个饼图边框的末尾,我们可以使用箭头符号吗? - 添加了示例设计图像
最规范的做法 是使用
marker-end
。不过,对于您的用例,我认为在正确的位置绘制箭头并进行正确的旋转会更容易:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.8.5/d3.js"></script>
</head>
<body>
<svg></svg>
<script>
const createWheel = () => {
const width = 200;
const height = 200;
const outerRadius = 100;
const innerRadius = 0;
const borderWidth = 1;
const spaceBetweenSlices = 10;
const arrowSize = 30;
const padding = 20;
const svg = d3
.select('svg')
.attr('width', width + padding * 2)
.attr('height', height + padding * 2)
.append('g')
.attr(
'transform',
`translate(${width / 2 + padding},${height / 2 + padding})`
);
const pie = d3.pie();
const data = [Math.random() * 10, Math.random() * 10, Math.random() * 10, Math.random() * 10, Math.random() * 10, Math.random() * 10];
const pieData = pie(data);
const arc = d3.arc().innerRadius(innerRadius).outerRadius(outerRadius);
const arcs = svg.selectAll('arc').data(pieData).enter()
.append("g")
.attr("class", "arc");
arcs
.append('path')
.attr('d', arc)
.attr('fill', (d, i) => d3.schemeCategory10[i]);
const borderArc = d3
.arc()
.innerRadius(outerRadius + spaceBetweenSlices)
.outerRadius(outerRadius + borderWidth + spaceBetweenSlices);
arcs
.append('path')
.attr('d', borderArc)
.attr('fill', 'none')
.attr('stroke', (d, i) => d3.schemeCategory10[i])
.attr('stroke-width', borderWidth);
// Add greater-than signs at the end of each border
arcs
.append('path')
.attr('d', 'M-10,-10 L0,0 L10,-10')
.attr('transform', (d, i, j) => {
let x =
(outerRadius + spaceBetweenSlices) *
Math.cos(d.endAngle - Math.PI/2);
let y =
(outerRadius + spaceBetweenSlices) *
Math.sin(d.endAngle - Math.PI/2);
return 'translate(' + x + ',' + y + '), rotate(' + ((d.endAngle * 180/Math.PI) - 90) + ')';
})
.attr('fill', 'none')
.attr('stroke', (d, i) => d3.schemeCategory10[i])
.attr('stroke-width', borderWidth * 2);
};
createWheel();
</script>
</body>
</html>