Change look of highlighted pie slices (#33841)

pull/33832/head
Oscar Kilhed 4 years ago committed by GitHub
parent 0af75106e9
commit 4e7db598f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 150
      public/app/plugins/panel/piechart/PieChart.tsx

@ -1,6 +1,13 @@
import React, { FC } from 'react';
import React, { FC, useCallback } from 'react';
import { FieldDisplay, FALLBACK_COLOR, formattedValueToString, GrafanaTheme2 } from '@grafana/data';
import {
FieldDisplay,
FALLBACK_COLOR,
formattedValueToString,
GrafanaTheme2,
DataHoverClearEvent,
DataHoverEvent,
} from '@grafana/data';
import {
VizTooltipOptions,
useTheme2,
@ -8,6 +15,7 @@ import {
SeriesTableRowProps,
DataLinksContextMenu,
SeriesTable,
usePanelContext,
} from '@grafana/ui';
import { PieChartType, PieChartLabels } from './types';
import { useTooltip, useTooltipInPortal } from '@visx/tooltip';
@ -110,15 +118,16 @@ export const PieChart: FC<PieChartProps> = ({
{(pie) => (
<>
{pie.arcs.map((arc) => {
let color = arc.data.display.color ?? FALLBACK_COLOR;
const highlighted = highlightedTitle === arc.data.display.title;
const color = arc.data.display.color ?? FALLBACK_COLOR;
const highlightState = getHighlightState(highlightedTitle, arc);
if (arc.data.hasLinks && arc.data.getLinks) {
return (
<DataLinksContextMenu config={arc.data.field} key={arc.index} links={arc.data.getLinks}>
{(api) => (
<PieSlice
tooltip={tooltip}
highlighted={highlighted}
highlightState={highlightState}
arc={arc}
pie={pie}
fill={getGradientColor(color)}
@ -132,7 +141,7 @@ export const PieChart: FC<PieChartProps> = ({
return (
<PieSlice
key={arc.index}
highlighted={highlighted}
highlightState={highlightState}
tooltip={tooltip}
arc={arc}
pie={pie}
@ -143,17 +152,21 @@ export const PieChart: FC<PieChartProps> = ({
}
})}
{showLabel &&
pie.arcs.map((arc) => (
<PieLabel
arc={arc}
key={arc.index}
outerRadius={layout.outerRadius}
innerRadius={layout.innerRadius}
displayLabels={displayLabels}
total={total}
color={theme.colors.text.primary}
/>
))}
pie.arcs.map((arc) => {
const highlightState = getHighlightState(highlightedTitle, arc);
return (
<PieLabel
arc={arc}
key={arc.index}
highlightState={highlightState}
outerRadius={layout.outerRadius}
innerRadius={layout.innerRadius}
displayLabels={displayLabels}
total={total}
color={theme.colors.text.primary}
/>
);
})}
</>
)}
</Pie>
@ -178,32 +191,64 @@ export const PieChart: FC<PieChartProps> = ({
interface SliceProps {
arc: PieArcDatum<FieldDisplay>;
pie: ProvidedProps<FieldDisplay>;
highlighted?: boolean;
highlightState: HighLightState;
fill: string;
tooltip: UseTooltipParams<SeriesTableRowProps[]>;
tooltipOptions: VizTooltipOptions;
openMenu?: (event: React.MouseEvent<SVGElement>) => void;
}
function PieSlice({ arc, pie, highlighted, openMenu, fill, tooltip, tooltipOptions }: SliceProps) {
function PieSlice({ arc, pie, highlightState, openMenu, fill, tooltip, tooltipOptions }: SliceProps) {
const theme = useTheme2();
const styles = useStyles2(getStyles);
const { eventBus } = usePanelContext();
const onMouseMoveOverArc = (event: any) => {
const coords = localPoint(event.target.ownerSVGElement, event);
tooltip.showTooltip({
tooltipLeft: coords!.x,
tooltipTop: coords!.y,
tooltipData: getTooltipData(pie, arc, tooltipOptions),
});
};
const onMouseOut = useCallback(
(event: any) => {
eventBus?.publish({
type: DataHoverClearEvent.type,
payload: {
raw: event,
x: 0,
y: 0,
dataId: arc.data.display.title,
},
});
tooltip.hideTooltip();
},
[eventBus, arc, tooltip]
);
const onMouseMoveOverArc = useCallback(
(event: any) => {
eventBus?.publish({
type: DataHoverEvent.type,
payload: {
raw: event,
x: 0,
y: 0,
dataId: arc.data.display.title,
},
});
const coords = localPoint(event.target.ownerSVGElement, event);
tooltip.showTooltip({
tooltipLeft: coords!.x,
tooltipTop: coords!.y,
tooltipData: getTooltipData(pie, arc, tooltipOptions),
});
},
[eventBus, arc, tooltip, pie, tooltipOptions]
);
const pieStyle = getSvgStyle(highlightState, styles);
return (
<g
key={arc.data.display.title}
className={highlighted ? styles.svgArg.highlighted : styles.svgArg.normal}
className={pieStyle}
onMouseMove={tooltipOptions.mode !== 'none' ? onMouseMoveOverArc : undefined}
onMouseOut={tooltip.hideTooltip}
onMouseOut={onMouseOut}
onClick={openMenu}
aria-label={selectors.components.Panels.Visualization.PieChart.svgSlice}
>
@ -217,11 +262,13 @@ interface LabelProps {
outerRadius: number;
innerRadius: number;
displayLabels: PieChartLabels[];
highlightState: HighLightState;
total: number;
color: string;
}
function PieLabel({ arc, outerRadius, innerRadius, displayLabels, total, color }: LabelProps) {
function PieLabel({ arc, outerRadius, innerRadius, displayLabels, total, color, highlightState }: LabelProps) {
const styles = useStyles2(getStyles);
const labelRadius = innerRadius === 0 ? outerRadius / 6 : innerRadius;
const [labelX, labelY] = getLabelPos(arc, outerRadius, labelRadius);
const hasSpaceForLabel = arc.endAngle - arc.startAngle >= 0.3;
@ -235,7 +282,7 @@ function PieLabel({ arc, outerRadius, innerRadius, displayLabels, total, color }
: Math.min(Math.max((outerRadius / 100) * 14, 12), 36);
return (
<g>
<g className={getSvgStyle(highlightState, styles)}>
<text
fill={color}
x={labelX}
@ -334,6 +381,40 @@ function getPieLayout(height: number, width: number, pieType: PieChartType, marg
};
}
enum HighLightState {
Highlighted,
Deemphasized,
Normal,
}
function getHighlightState(highlightedTitle: string | undefined, arc: PieArcDatum<FieldDisplay>) {
if (highlightedTitle) {
if (highlightedTitle === arc.data.display.title) {
return HighLightState.Highlighted;
} else {
return HighLightState.Deemphasized;
}
}
return HighLightState.Normal;
}
function getSvgStyle(
highlightState: HighLightState,
styles: {
svgArg: { normal: string; highlighted: string; deemphasized: string };
}
) {
switch (highlightState) {
case HighLightState.Highlighted:
return styles.svgArg.highlighted;
case HighLightState.Deemphasized:
return styles.svgArg.deemphasized;
case HighLightState.Normal:
default:
return styles.svgArg.normal;
}
}
const getStyles = (theme: GrafanaTheme2) => {
return {
container: css`
@ -346,14 +427,15 @@ const getStyles = (theme: GrafanaTheme2) => {
svgArg: {
normal: css`
transition: all 200ms ease-in-out;
&:hover {
transform: scale3d(1.03, 1.03, 1);
}
`,
highlighted: css`
transition: all 200ms ease-in-out;
transform: scale3d(1.03, 1.03, 1);
`,
deemphasized: css`
transition: all 200ms ease-in-out;
fill-opacity: 0.5;
`,
},
tooltipPortal: css`
${getTooltipContainerStyles(theme)}

Loading…
Cancel
Save