Skip to content

Instantly share code, notes, and snippets.

@LukeChannings
Created March 17, 2020 16:08
Show Gist options
  • Save LukeChannings/4fed2e9a9a40e0d086ccd3d31db8d398 to your computer and use it in GitHub Desktop.
Save LukeChannings/4fed2e9a9a40e0d086ccd3d31db8d398 to your computer and use it in GitHub Desktop.
import React, { memo } from "react";
import {
pie,
arc,
extent,
interpolateSinebow,
PieArcDatum
} from "d3";
import { formatCurrency } from "../lib/monzo";
import { jsonEqual } from "../util";
interface PieChartPiece {
value: number;
label: string;
}
interface PieChartProps {
items: PieChartPiece[];
width: number;
height: number;
labelOffset?: [number, number];
}
export const PieChart = memo(function PieChart({
items,
width,
height,
labelOffset: [labelOffsetOuter, labelOffsetInner] = [80, 80],
}: PieChartProps) {
const [min, max] = extent(items, d => d.value);
const radius = width / 2;
const pieGenerator = pie<PieChartPiece>().value(d => d.value).padAngle(0.05);
const pieArc = arc<PieArcDatum<PieChartPiece>>()
.outerRadius(radius - 10)
.innerRadius(radius - 120)
.cornerRadius(10);
const labelArc = arc<PieArcDatum<PieChartPiece>>()
.outerRadius(radius - labelOffsetOuter)
.innerRadius(radius - labelOffsetInner)
.cornerRadius(10);
return (
<svg width={width} height={height}>
<g transform={`translate(${width / 2}, ${height / 2})`}>
{pieGenerator(items).map(d => (
<g key={d.value}>
<path
d={pieArc(d) ?? ''}
fill={interpolateSinebow((d.value - (min ?? 0)) / (max ?? 100))}
/>
{
d.startAngle - d.endAngle < -0.3 && (
<text className="text-xs" transform={`translate(${labelArc.centroid(d)})`}>
{d.data.label}
</text>
)
}
</g>
))}
</g>
</svg>
);
}, jsonEqual);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment