Skip to content

Commit

Permalink
feat(scatterplot): add ability to specify nodeId accessor
Browse files Browse the repository at this point in the history
  • Loading branch information
wyze authored and plouc committed Jun 7, 2021
1 parent 12d8450 commit 343ef6f
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 21 deletions.
7 changes: 7 additions & 0 deletions packages/scatterplot/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
MotionProps,
CartesianMarkerProps,
CssMixBlendMode,
PropertyAccessor,
} from '@nivo/core'
import { OrdinalColorScaleConfig } from '@nivo/colors'
import { LegendProps } from '@nivo/legends'
Expand All @@ -31,6 +32,11 @@ declare module '@nivo/scatterplot' {
y: Value
}

export interface NodeIdDatum extends Record<string, string | number> {
serieId: Serie['id']
index: number
}

export type DerivedDatumProp<T> = (node: Datum) => T

export interface Serie {
Expand Down Expand Up @@ -138,6 +144,7 @@ declare module '@nivo/scatterplot' {
axisBottom?: AxisProps | null
axisLeft?: AxisProps | null

nodeId?: PropertyAccessor<NodeIdDatum, string>
nodeSize?: number | DerivedDatumProp<number> | DynamicSizeSpec | DerivedNodeProp<number>

isInteractive?: boolean
Expand Down
2 changes: 2 additions & 0 deletions packages/scatterplot/src/ScatterPlot.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const ScatterPlot = props => {
colors,
blendMode,

nodeId,
nodeSize,
renderNode,

Expand Down Expand Up @@ -87,6 +88,7 @@ const ScatterPlot = props => {
yFormat,
width: innerWidth,
height: innerHeight,
nodeId,
nodeSize,
colors,
})
Expand Down
32 changes: 18 additions & 14 deletions packages/scatterplot/src/compute.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,27 @@ export const getNodeSizeGenerator = size => {
throw new Error('symbolSize is invalid, it should be either a function, a number or an object')
}

export const computePoints = ({ series, formatX, formatY }) => {
export const computePoints = ({ series, formatX, formatY, getNodeId }) => {
return series.reduce(
(agg, serie) => [
...agg,
...serie.data.map((d, i) => ({
index: agg.length + i,
id: `${serie.id}.${i}`,
x: d.position.x,
y: d.position.y,
data: {
...d.data,
id: `${serie.id}.${i}`,
serieId: serie.id,
formattedX: formatX(d.data.x),
formattedY: formatY(d.data.y),
},
})),
...serie.data.map((d, index) => {
const id = getNodeId({ serieId: serie.id, index, ...d.data })

return {
index: agg.length + index,
id,
x: d.position.x,
y: d.position.y,
data: {
...d.data,
id,
serieId: serie.id,
formattedX: formatX(d.data.x),
formattedY: formatY(d.data.y),
},
}
}),
],
[]
)
Expand Down
7 changes: 5 additions & 2 deletions packages/scatterplot/src/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* file that was distributed with this source code.
*/
import { useMemo } from 'react'
import { useValueFormatter } from '@nivo/core'
import { useValueFormatter, usePropertyAccessor } from '@nivo/core'
import { useOrdinalColorScale } from '@nivo/colors'
import { computeXYScalesForSeries } from '@nivo/scales'
import { useAnnotations } from '@nivo/annotations'
Expand All @@ -23,6 +23,7 @@ export const useScatterPlot = ({
yFormat,
width,
height,
nodeId,
nodeSize,
colors,
}) => {
Expand All @@ -33,10 +34,12 @@ export const useScatterPlot = ({

const formatX = useValueFormatter(xFormat)
const formatY = useValueFormatter(yFormat)
const rawNodes = useMemo(() => computePoints({ series, formatX, formatY }), [
const getNodeId = usePropertyAccessor(nodeId)
const rawNodes = useMemo(() => computePoints({ series, formatX, formatY, getNodeId }), [
series,
formatX,
formatY,
getNodeId,
])

const getNodeSize = useNodeSize(nodeSize)
Expand Down
1 change: 1 addition & 0 deletions packages/scatterplot/src/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ const commonDefaultProps = {
axisBottom: {},
axisLeft: {},

nodeId: ({ serieId, index }) => `${serieId}.${index}`,
nodeSize: 9,
renderNode: Node,

Expand Down
21 changes: 16 additions & 5 deletions website/src/data/components/scatterplot/props.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ const props = [
If you use a time scale, you must provide a time format
as values are converted to Date objects.
Under the hood, nivo uses [d3-format](https://github.com/d3/d3-format),
please have a look at it for available formats, you can also pass a function
which will receive the raw value and should return the formatted one.
Expand Down Expand Up @@ -165,12 +165,24 @@ const props = [
If you use a time scale, you must provide a time format
as values are converted to Date objects.
Under the hood, nivo uses [d3-format](https://github.com/d3/d3-format),
please have a look at it for available formats, you can also pass a function
which will receive the raw value and should return the formatted one.
`,
},
{
key: 'nodeId',
group: 'Base',
defaultValue: defaults.nodeId,
type: 'string | (datum: NodeIdDatum): string',
help: `ID accessor for the node.`,
description: `
Define how to determine the id of each node on the plot.
By default nivo will join together the serie.id and datum index.
`,
},
{
key: 'nodeSize',
group: 'Base',
Expand Down Expand Up @@ -306,7 +318,7 @@ const props = [
You can also use this to insert extra layers
to the chart.
For \`ScatterPlot\`, the extra layer should be a component
and will receive current chart context as props.
Expand Down Expand Up @@ -395,7 +407,7 @@ const props = [
A function allowing complete tooltip customisation,
it must return a valid HTML element and will
receive the node as a property.
You can also customize the tooltip style
using the \`theme.tooltip\` object.
`,
Expand Down Expand Up @@ -428,7 +440,6 @@ const props = [
type: '(node, event) => void',
required: false,
},
,
{
key: 'legends',
group: 'Legends',
Expand Down

0 comments on commit 343ef6f

Please sign in to comment.