From 4e7db598f544a512c05d08ad98369b6bd342bceb Mon Sep 17 00:00:00 2001 From: Oscar Kilhed Date: Mon, 10 May 2021 12:59:38 +0200 Subject: [PATCH] Change look of highlighted pie slices (#33841) --- .../app/plugins/panel/piechart/PieChart.tsx | 150 ++++++++++++++---- 1 file changed, 116 insertions(+), 34 deletions(-) diff --git a/public/app/plugins/panel/piechart/PieChart.tsx b/public/app/plugins/panel/piechart/PieChart.tsx index 015f1caf76c..1916fdcd5b3 100644 --- a/public/app/plugins/panel/piechart/PieChart.tsx +++ b/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 = ({ {(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 ( {(api) => ( = ({ return ( = ({ } })} {showLabel && - pie.arcs.map((arc) => ( - - ))} + pie.arcs.map((arc) => { + const highlightState = getHighlightState(highlightedTitle, arc); + return ( + + ); + })} )} @@ -178,32 +191,64 @@ export const PieChart: FC = ({ interface SliceProps { arc: PieArcDatum; pie: ProvidedProps; - highlighted?: boolean; + highlightState: HighLightState; fill: string; tooltip: UseTooltipParams; tooltipOptions: VizTooltipOptions; openMenu?: (event: React.MouseEvent) => 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 ( @@ -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 ( - + ) { + 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)}