Add labels

This commit is contained in:
Jared He 2022-06-18 22:35:39 -04:00
parent ea6e2d4c7a
commit b931afd7cc
3 changed files with 69 additions and 44 deletions

View File

@ -1,18 +1,28 @@
.path { .piePath {
fill: #354265; fill: #354265;
} }
.text { .labelPath {
display: none; fill: var(--primary-background);
fill: white;
font-weight: 800;
} }
.group:hover>.path { .pieText,
.labelText {
fill: white;
font-size: 20px;
font-weight: 800;
font-family: "Inconsolata", "sans-serif";
}
.pieText {
display: none;
}
.group:hover>.piePath {
fill: #EF839D; fill: #EF839D;
filter: drop-shadow(0px 0px 6px #CC5773); filter: drop-shadow(0px 0px 6px #CC5773);
} }
.group:hover>.text { .group:hover>.pieText {
display: inline display: inline
} }

View File

@ -1,4 +1,5 @@
import { Group } from "@visx/group"; import { Group } from "@visx/group";
import { Arc } from "@visx/shape";
import Pie, { ProvidedProps } from "@visx/shape/lib/shapes/Pie"; import Pie, { ProvidedProps } from "@visx/shape/lib/shapes/Pie";
import React, { useState } from "react"; import React, { useState } from "react";
@ -7,13 +8,7 @@ import styles from "./PieChart.module.css";
interface PieChartProps { interface PieChartProps {
data: PieChartData[]; data: PieChartData[];
width: number; width: number;
height: number; textPadding: number;
margin: {
top: number;
bottom: number;
left: number;
right: number;
};
className?: string; className?: string;
} }
@ -22,19 +17,31 @@ interface PieChartData {
value: number; value: number;
} }
export function PieChart(props: PieChartProps) { export function PieChart({ width, textPadding, ...props }: PieChartProps) {
const pieWidth = width * 0.5 - textPadding;
return ( return (
<svg className={props.className} width={props.width} height={props.height}> <svg className={props.className} width={width} height={width}>
<Group top={props.margin.top} left={props.margin.left}> <Group top={width * 0.5} left={width * 0.5}>
<Pie <Pie
data={props.data} data={props.data}
fill="aqua" fill="aqua"
pieValue={(d: PieChartData) => d.value} pieValue={(d: PieChartData) => d.value}
outerRadius={100} cornerRadius={10}
cornerRadius={5} padAngle={0.075}
padAngle={0.1} padRadius={width * 0.7}
innerRadius={width * 0.03}
outerRadius={pieWidth}
> >
{(pie) => <PieSlice {...pie} />} {(pie) => <PieSlices {...pie} isLabel={false} />}
</Pie>
<Pie
data={props.data}
fill="rgb(37, 45, 65)"
pieValue={(d: PieChartData) => d.value}
innerRadius={pieWidth}
outerRadius={width * 0.5}
>
{(pie) => <PieSlices {...pie} isLabel={true} />}
</Pie> </Pie>
</Group> </Group>
</svg> </svg>
@ -42,23 +49,34 @@ export function PieChart(props: PieChartProps) {
} }
// path, arcs, pie // path, arcs, pie
type PieSliceProps<PieChartData> = ProvidedProps<PieChartData>; type PieSlicesProps<PieChartData> = ProvidedProps<PieChartData> & {
isLabel: boolean;
};
export function PieSlice(props: PieSliceProps<PieChartData>) { export function PieSlices({ isLabel, ...props }: PieSlicesProps<PieChartData>) {
return props.arcs.map((arc) => { return (
const [centroidX, centroidY] = props.path.centroid(arc); <>
const pathArc = props.path(arc); {props.arcs.map((arc) => {
const [centroidX, centroidY] = props.path.centroid(arc);
const pathArc = props.path(arc);
return ( return (
<g key={`arc-${arc.data.category}`} className={styles.group}> <g className={styles.group} key={`arc-${arc.data.category}`}>
<path className={styles.path} d={pathArc} /> <path
<text className={isLabel ? styles.labelPath : styles.piePath}
className={styles.text} d={pathArc}
x={centroidX} />
y={centroidY} <text
textAnchor="middle" className={isLabel ? styles.labelText : styles.pieText}
>{`${arc.data.value}%`}</text> x={centroidX}
</g> y={centroidY}
); textAnchor="middle"
}); >
{isLabel ? `${arc.data.category}` : `${arc.data.value}%`}
</text>
</g>
);
})}
</>
);
} }

View File

@ -8,12 +8,9 @@ export default function Home() {
<> <>
<h1>Playground</h1> <h1>Playground</h1>
<p>Show off your components here!</p> <p>Show off your components here!</p>
<PieChart <div style={{ padding: "30px" }}>
data={mockPieData} <PieChart data={mockPieData} width={600} textPadding={100} />
width={500} </div>
height={500}
margin={{ top: 100, left: 100, bottom: 100, right: 100 }}
/>
</> </>
); );
} }