Skip to content

Commit

Permalink
feat(scatterplot): migrate from react-motion to react-spring
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Aug 28, 2021
1 parent 34e6d37 commit c1b84c9
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 312 deletions.
69 changes: 0 additions & 69 deletions packages/scatterplot/AnimatedNodes.tsx

This file was deleted.

53 changes: 0 additions & 53 deletions packages/scatterplot/old_index.d.ts

This file was deleted.

46 changes: 28 additions & 18 deletions packages/scatterplot/src/Node.tsx
@@ -1,25 +1,35 @@
import { ScatterPlotNodeProps, ScatterPlotDatum } from './types'
import { animated } from '@react-spring/web'
import { ScatterPlotDatum, ScatterPlotNodeProps } from './types'
import { useCallback } from 'react'

const interpolateRadius = (size: number) => size / 2

export const Node = <RawDatum extends ScatterPlotDatum>({
x,
y,
size,
color,
node,
style,
blendMode,
isInteractive,
onMouseEnter,
onMouseMove,
onMouseLeave,
onClick,
}: ScatterPlotNodeProps<RawDatum>) => (
<circle
cx={x}
cy={y}
r={size / 2}
fill={color}
style={{ mixBlendMode: blendMode }}
onMouseEnter={onMouseEnter}
onMouseMove={onMouseMove}
onMouseLeave={onMouseLeave}
onClick={onClick}
/>
)
}: ScatterPlotNodeProps<RawDatum>) => {
const handleMouseEnter = useCallback(event => onMouseEnter?.(node, event), [node, onMouseEnter])
const handleMouseMove = useCallback(event => onMouseMove?.(node, event), [node, onMouseMove])
const handleMouseLeave = useCallback(event => onMouseLeave?.(node, event), [node, onMouseLeave])
const handleClick = useCallback(event => onClick?.(node, event), [node, onClick])

return (
<animated.circle
cx={style.x}
cy={style.y}
r={style.size.to(interpolateRadius)}
fill={style.color}
style={{ mixBlendMode: blendMode }}
onMouseEnter={isInteractive ? handleMouseEnter : undefined}
onMouseMove={isInteractive ? handleMouseMove : undefined}
onMouseLeave={isInteractive ? handleMouseLeave : undefined}
onClick={isInteractive ? handleClick : undefined}
/>
)
}
87 changes: 0 additions & 87 deletions packages/scatterplot/src/NodeWrapper.tsx

This file was deleted.

113 changes: 113 additions & 0 deletions packages/scatterplot/src/Nodes.tsx
@@ -0,0 +1,113 @@
import { useTransition } from '@react-spring/web'
import { CssMixBlendMode, useMotionConfig } from '@nivo/core'
import { useTooltip } from '@nivo/tooltip'
import {
ScatterPlotCommonProps,
ScatterPlotDatum,
ScatterPlotNode,
ScatterPlotNodeData,
} from './types'
import { createElement, useCallback } from 'react'

interface NodesProps<RawDatum extends ScatterPlotDatum> {
nodes: ScatterPlotNodeData<RawDatum>[]
nodeComponent: ScatterPlotNode<RawDatum>
isInteractive: boolean
onMouseEnter?: ScatterPlotCommonProps<RawDatum>['onMouseEnter']
onMouseMove?: ScatterPlotCommonProps<RawDatum>['onMouseMove']
onMouseLeave?: ScatterPlotCommonProps<RawDatum>['onMouseLeave']
onClick?: ScatterPlotCommonProps<RawDatum>['onClick']
tooltip: ScatterPlotCommonProps<RawDatum>['tooltip']
blendMode: CssMixBlendMode
}

const getNodeKey = <RawDatum extends ScatterPlotDatum>(node: ScatterPlotNodeData<RawDatum>) =>
node.id
const regularTransition = <RawDatum extends ScatterPlotDatum>(
node: ScatterPlotNodeData<RawDatum>
) => ({
x: node.x,
y: node.y,
size: node.size,
color: node.style.color,
})
const leaveTransition = <RawDatum extends ScatterPlotDatum>(
node: ScatterPlotNodeData<RawDatum>
) => ({
x: node.x,
y: node.y,
size: 0,
color: node.style.color,
})

export const Nodes = <RawDatum extends ScatterPlotDatum>({
nodes,
nodeComponent,
isInteractive,
onMouseEnter,
onMouseMove,
onMouseLeave,
onClick,
tooltip,
blendMode,
}: NodesProps<RawDatum>) => {
const { animate, config: springConfig } = useMotionConfig()
const transition = useTransition<
ScatterPlotNodeData<RawDatum>,
{
x: number
y: number
size: number
color: string
}
>(nodes, {
keys: getNodeKey,
from: regularTransition,
enter: regularTransition,
update: regularTransition,
leave: leaveTransition,
config: springConfig,
immediate: !animate,
})

const { showTooltipFromEvent, hideTooltip } = useTooltip()
const handleMouseEnter = useCallback(
(node, event) => {
showTooltipFromEvent(createElement(tooltip, { node }), event)
onMouseEnter?.(node, event)
},
[tooltip, showTooltipFromEvent, onMouseEnter]
)
const handleMouseMove = useCallback(
(node, event) => {
showTooltipFromEvent(createElement(tooltip, { node }), event)
onMouseMove?.(node, event)
},
[tooltip, showTooltipFromEvent, onMouseMove]
)
const handleMouseLeave = useCallback(
(node, event) => {
hideTooltip()
onMouseLeave?.(node, event)
},
[hideTooltip, onMouseLeave]
)
const handleClick = useCallback((node, event) => onClick?.(node, event), [onClick])

return (
<>
{transition((style, node) =>
createElement(nodeComponent, {
node,
style,
blendMode,
isInteractive,
onMouseEnter: isInteractive ? handleMouseEnter : undefined,
onMouseMove: isInteractive ? handleMouseMove : undefined,
onMouseLeave: isInteractive ? handleMouseLeave : undefined,
onClick: isInteractive ? handleClick : undefined,
})
)}
</>
)
}

0 comments on commit c1b84c9

Please sign in to comment.