Skip to content

Commit

Permalink
new(xychart/BarGroup): add mouseover/out
Browse files Browse the repository at this point in the history
  • Loading branch information
williaster committed Oct 13, 2020
1 parent 8ee99bb commit bf3870d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/visx-demo/src/sandboxes/visx-xychart/Example.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -147,8 +147,8 @@ export default function Example({ height }: Props) {
showVerticalCrosshair={showVerticalCrosshair}
snapTooltipToDatumX={snapTooltipToDatumX}
snapTooltipToDatumY={snapTooltipToDatumY}
showDatumGlyph={snapTooltipToDatumX || snapTooltipToDatumY}
showSeriesGlyphs={sharedTooltip}
showDatumGlyph={(snapTooltipToDatumX || snapTooltipToDatumY) && !renderBarGroup}
showSeriesGlyphs={sharedTooltip && !renderBarGroup}
renderTooltip={({ tooltipData, colorScale }) => (
<>
{/** date */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,8 @@ export default function ExampleControls({ children }: ControlsProps) {
showHorizontalCrosshair,
showTooltip,
showVerticalCrosshair,
snapTooltipToDatumX: renderBarStackOrGroup === 'bar' && snapTooltipToDatumX,
snapTooltipToDatumY: renderBarStackOrGroup === 'bar' && snapTooltipToDatumY,
snapTooltipToDatumX: renderBarStackOrGroup !== 'stack' && snapTooltipToDatumX,
snapTooltipToDatumY: renderBarStackOrGroup !== 'stack' && snapTooltipToDatumY,
theme,
xAxisOrientation,
yAxisOrientation,
Expand Down Expand Up @@ -314,7 +314,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="checkbox"
disabled={!showTooltip || renderBarStackOrGroup !== 'bar'}
disabled={!showTooltip || renderBarStackOrGroup === 'stack'}
onChange={() => setSnapTooltipToDatumX(!snapTooltipToDatumX)}
checked={showTooltip && snapTooltipToDatumX}
/>{' '}
Expand All @@ -323,7 +323,7 @@ export default function ExampleControls({ children }: ControlsProps) {
<label>
<input
type="checkbox"
disabled={!showTooltip || renderBarStackOrGroup !== 'bar'}
disabled={!showTooltip || renderBarStackOrGroup === 'stack'}
onChange={() => setSnapTooltipToDatumY(!snapTooltipToDatumY)}
checked={showTooltip && snapTooltipToDatumY}
/>{' '}
Expand Down
58 changes: 53 additions & 5 deletions packages/visx-xychart/src/components/series/BarGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,21 @@ import { PositionScale } from '@visx/shape/lib/types';
import { scaleBand } from '@visx/scale';
import isChildWithProps from '../../typeguards/isChildWithProps';
import { BarSeriesProps } from './BarSeries';
import { DataContextType, DataRegistryEntry } from '../../types';
import { DataContextType } from '../../types';
import DataContext from '../../context/DataContext';
import getScaleBandwidth from '../../utils/getScaleBandwidth';
import isValidNumber from '../../typeguards/isValidNumber';
import findNearestDatumY from '../../utils/findNearestDatumY';
import findNearestDatumX from '../../utils/findNearestDatumX';
import useEventEmitter, { HandlerParams } from '../../hooks/useEventEmitter';
import TooltipContext from '../../context/TooltipContext';

export type BarGroupProps = {
/** Whether to render the Stack horizontally instead of vertically. */
horizontal?: boolean;
/** `BarSeries` elements */
children: JSX.Element | JSX.Element[];
/** Group scale padding */
/** Group band scale padding, [0, 1] where 0 = no padding, 1 = no bar. */
padding?: number;
};

Expand All @@ -22,9 +26,16 @@ export default function BarGroup<
YScale extends PositionScale,
Datum extends object
>({ children, horizontal, padding = 0.1 }: BarGroupProps) {
const { xScale, yScale, colorScale, dataRegistry, registerData, unregisterData } = (useContext(
DataContext,
) as unknown) as DataContextType<XScale, YScale, Datum>;
const {
xScale,
yScale,
colorScale,
dataRegistry,
registerData,
unregisterData,
width,
height,
} = (useContext(DataContext) as unknown) as DataContextType<XScale, YScale, Datum>;

const barSeriesChildren = useMemo(
() =>
Expand All @@ -51,6 +62,7 @@ export default function BarGroup<
return () => unregisterData(dataKeys);
}, [registerData, unregisterData, barSeriesChildren, dataKeys]);

// create group scale
const groupScale = useMemo(
() =>
scaleBand<string>({
Expand All @@ -61,7 +73,43 @@ export default function BarGroup<
[dataKeys, xScale, yScale, horizontal, padding],
);

const { showTooltip, hideTooltip } = useContext(TooltipContext) ?? {};
const handleMouseMove = useCallback(
(params?: HandlerParams) => {
const { svgPoint } = params || {};
// invoke showTooltip for each key so all data is available in context,
// and let Tooltip find the nearest point among them
dataKeys.forEach(key => {
const entry = dataRegistry.get(key);

if (entry && svgPoint && width && height && showTooltip) {
const datum = (horizontal ? findNearestDatumY : findNearestDatumX)({
point: svgPoint,
data: entry.data,
xScale,
yScale,
xAccessor: entry.xAccessor,
yAccessor: entry.yAccessor,
width,
height,
});
if (datum) {
showTooltip({
key,
...datum,
svgPoint,
});
}
}
});
},
[dataKeys, dataRegistry, horizontal, xScale, yScale, width, height, showTooltip],
);
useEventEmitter('mousemove', handleMouseMove);
useEventEmitter('mouseout', hideTooltip);

const registryEntries = dataKeys.map(key => dataRegistry.get(key));

// if scales and data are not available in the registry, bail
if (registryEntries.some(entry => entry == null) || !xScale || !yScale || !colorScale) {
return null;
Expand Down

0 comments on commit bf3870d

Please sign in to comment.