Skip to content

Commit

Permalink
fix: remove always on labels from pie chart
Browse files Browse the repository at this point in the history
  • Loading branch information
MauriceNino committed Jun 28, 2022
1 parent ac7c99e commit 86360a9
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 41 deletions.
92 changes: 56 additions & 36 deletions apps/view/src/components/chart-components.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { FC, useMemo, useState } from 'react';
import { motion } from 'framer-motion';
import { FC, useMemo, useRef, useState } from 'react';
import {
Area,
AreaChart,
Expand All @@ -11,7 +12,7 @@ import {
YAxis,
} from 'recharts';
import styled, { useTheme } from 'styled-components';
import { ThemedText } from './text';
import { throttle } from 'throttle-debounce';

type DefaultAreaChartProps = {
height: number;
Expand Down Expand Up @@ -55,41 +56,44 @@ export const DefaultAreaChart: FC<DefaultAreaChartProps> = ({
);
};

const HoverLabel = styled(ThemedText)<{ top: number; left: number }>`
const HoverLabel = styled(motion.p)`
color: ${props => props.theme.colors.text};
position: absolute;
top: ${props => props.top - 40}px;
left: ${props => props.left - 20}px;
z-index: 999;
pointer-events: none;
transition: all 0.1s;
white-space: pre;
text-align: center;
line-height: 1.4;
`;

const renderLabel = (
{ cx, cy, midAngle, innerRadius, outerRadius, payload }: any,
theme: any,
labelRenderer: (value: number) => string
) => {
const radius = innerRadius + (outerRadius - innerRadius) * 0.5;
const centerx = cx + radius * Math.cos((-midAngle * Math.PI) / 180);
const centery = cy + radius * Math.sin((-midAngle * Math.PI) / 180);
const value = payload.value;

return value > 1 ? (
<text
x={centerx}
y={centery}
fill={theme.colors.text}
textAnchor={'middle'}
dominantBaseline='central'
style={{
pointerEvents: 'none',
}}
>
{labelRenderer(value)}
</text>
) : null;
};
const getCoords = (
pos: { x: number; y: number },
parent: { width: number; height: number },
label: { width: number; height: number }
): { top: number; left: number } => {
const { width: parentWidth, height: parentHeight } = parent;
const { width: labelWidth, height: labelHeight } = label;
const { x, y } = pos;

const topBottomOffset = labelHeight * (y > parentHeight / 2 ? -1 : 1) + 10;
const top = y - labelHeight / 2 + topBottomOffset;
const left = x - labelWidth / 2;

if (top < 0) {
return { top: 10, left };
}
if (top + labelHeight > parentHeight) {
return { top: parentHeight - labelHeight - 10, left };
}
if (left < 0) {
return { top, left: 10 };
}
if (left + labelWidth > parentWidth) {
return { top, left: parentWidth - labelWidth - 10 };
}

return { top, left };
};
const renderActiveShape = (props: any) => {
return <Sector {...props} outerRadius={props.outerRadius * 1.08} />;
};
Expand All @@ -101,7 +105,6 @@ type DefaultPieChartProps = {
color: string;
children: React.ReactNode;
data: any[];
labelRenderer: (value: number) => string;
hoverLabelRenderer: (label: string, value: number) => string;
};
export const DefaultPieChart: FC<DefaultPieChartProps> = ({
Expand All @@ -110,14 +113,15 @@ export const DefaultPieChart: FC<DefaultPieChartProps> = ({
width,
color,
children,
labelRenderer,
hoverLabelRenderer,
}) => {
const id = useMemo(() => {
return `pie-chart-${++globalId}`;
}, []);
const theme = useTheme();

const labelRef = useRef<HTMLParagraphElement>(null);

const [activeSegment, setActiveSegment] = useState<number | undefined>(
undefined
);
Expand All @@ -129,13 +133,30 @@ export const DefaultPieChart: FC<DefaultPieChartProps> = ({
}
| undefined
>(undefined);
const throttledSetLabel = useMemo(
() => throttle(100, setLabel, { noTrailing: true }),
[]
);

const minSize = Math.min(height, width);
const labelWidth = labelRef.current?.offsetWidth || 0;
const labelHeight = labelRef.current?.offsetHeight || 0;

return (
<>
{label && (
<HoverLabel top={label.y} left={label.x}>
<HoverLabel
ref={labelRef}
initial={{
top: label.y,
left: label.x + 20,
}}
animate={getCoords(
label,
{ width, height },
{ width: labelWidth, height: labelHeight }
)}
>
{label.label}
</HoverLabel>
)}
Expand Down Expand Up @@ -169,15 +190,14 @@ export const DefaultPieChart: FC<DefaultPieChartProps> = ({
const label = data.payload.payload.name;
const value = data.payload.payload.value;

setLabel({
throttledSetLabel({
label: hoverLabelRenderer(label, value),
x: event.clientX - rect.left,
y: event.clientY - rect.top,
});
}}
activeShape={renderActiveShape}
labelLine={false}
label={props => renderLabel(props, theme, labelRenderer)}
>
{children}
</Pie>
Expand Down
12 changes: 7 additions & 5 deletions apps/view/src/widgets/storage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,14 @@ export const StorageChart: FC<StorageChartProps> = ({
return (
<>
<ThemedText>
{value ? (value.usedPercent * 100).toFixed(2) : 0} % Used
{value ? (value.usedPercent * 100).toFixed(1) : 0} % Used
</ThemedText>

<ThemedText>
({bytePrettyPrint(value?.used ?? 0)} /{' '}
{bytePrettyPrint(value?.used ?? 0)} /{' '}
{bytePrettyPrint(
(value?.available ?? 0) + (value?.used ?? 0)
)}
)
</ThemedText>
</>
);
Expand Down Expand Up @@ -230,9 +229,12 @@ export const StorageChart: FC<StorageChartProps> = ({
width={size.width}
height={size.height}
color={theme.colors.storagePrimary}
labelRenderer={val => bytePrettyPrint(val)}
hoverLabelRenderer={(label, value) =>
`${((value / totalSize) * 100).toFixed(1)}% ${label}`
`${((value / totalSize) * 100).toFixed(
1
)} % ${label}\n${bytePrettyPrint(value)} / ${bytePrettyPrint(
totalSize
)}`
}
>
<Cell
Expand Down

0 comments on commit 86360a9

Please sign in to comment.