diff --git a/packages/arcs/src/arcInterpolator.ts b/packages/arcs/src/arcInterpolator.ts new file mode 100644 index 000000000..f51a5d9ec --- /dev/null +++ b/packages/arcs/src/arcInterpolator.ts @@ -0,0 +1,21 @@ +import { to, SpringValue } from 'react-spring' +import { ArcGenerator } from './types' + +export const interpolateArc = ( + startAngleValue: SpringValue, + endAngleValue: SpringValue, + innerRadiusValue: SpringValue, + outerRadiusValue: SpringValue, + arcGenerator: ArcGenerator +) => + to( + [startAngleValue, endAngleValue, innerRadiusValue, outerRadiusValue], + (startAngle, endAngle, innerRadius, outerRadius) => { + return arcGenerator({ + startAngle, + endAngle, + innerRadius, + outerRadius, + }) + } + ) diff --git a/packages/arcs/src/index.ts b/packages/arcs/src/index.ts index 583d25fca..5c49cb5f4 100644 --- a/packages/arcs/src/index.ts +++ b/packages/arcs/src/index.ts @@ -1,3 +1,4 @@ export * from './types' export * from './useAnimatedArc' export * from './useArcGenerator' +export * from './useArcsTransition' diff --git a/packages/arcs/src/types.ts b/packages/arcs/src/types.ts index beac77fc2..cf27a2478 100644 --- a/packages/arcs/src/types.ts +++ b/packages/arcs/src/types.ts @@ -12,6 +12,7 @@ export interface Arc { } export interface DatumWithArc { + id: string | number arc: Arc } diff --git a/packages/arcs/src/useAnimatedArc.ts b/packages/arcs/src/useAnimatedArc.ts index 58a095752..b3a29f5b8 100644 --- a/packages/arcs/src/useAnimatedArc.ts +++ b/packages/arcs/src/useAnimatedArc.ts @@ -1,6 +1,7 @@ -import { to, useSpring } from 'react-spring' +import { useSpring } from 'react-spring' import { useMotionConfig } from '@nivo/core' import { Arc, ArcGenerator } from './types' +import { interpolateArc } from './arcInterpolator' export const useAnimatedArc = (datumWithArc: { arc: Arc }, arcGenerator: ArcGenerator) => { const { animate, config: springConfig } = useMotionConfig() @@ -16,20 +17,12 @@ export const useAnimatedArc = (datumWithArc: { arc: Arc }, arcGenerator: ArcGene return { ...animatedValues, - path: to( - [ - animatedValues.startAngle, - animatedValues.endAngle, - animatedValues.innerRadius, - animatedValues.outerRadius, - ], - (startAngle, endAngle, innerRadius, outerRadius) => - arcGenerator({ - startAngle, - endAngle, - innerRadius, - outerRadius, - }) + path: interpolateArc( + animatedValues.startAngle, + animatedValues.endAngle, + animatedValues.innerRadius, + animatedValues.outerRadius, + arcGenerator ), } } diff --git a/packages/arcs/src/useArcsTransition.ts b/packages/arcs/src/useArcsTransition.ts new file mode 100644 index 000000000..ad0a2eed5 --- /dev/null +++ b/packages/arcs/src/useArcsTransition.ts @@ -0,0 +1,58 @@ +import { useTransition } from 'react-spring' +import { useMotionConfig } from '@nivo/core' +import { DatumWithArc } from './types' +import { interpolateArc } from './arcInterpolator' + +export const useArcsTransition = (data: Datum[]) => { + console.log(data) + const { animate, config: springConfig } = useMotionConfig() + + const transition = useTransition< + Datum, + { + startAngle: number + endAngle: number + innerRadius: number + outerRadius: number + } + >(data, { + key: datum => datum.id, + initial: datum => ({ + startAngle: datum.arc.startAngle, + endAngle: datum.arc.endAngle, + innerRadius: datum.arc.innerRadius, + outerRadius: datum.arc.outerRadius, + }), + from: datum => ({ + startAngle: datum.arc.startAngle + (datum.arc.endAngle - datum.arc.startAngle) / 2, + endAngle: datum.arc.startAngle + (datum.arc.endAngle - datum.arc.startAngle) / 2, + innerRadius: datum.arc.innerRadius, + outerRadius: datum.arc.outerRadius, + }), + enter: datum => ({ + startAngle: datum.arc.startAngle, + endAngle: datum.arc.endAngle, + innerRadius: datum.arc.innerRadius, + outerRadius: datum.arc.outerRadius, + }), + update: datum => ({ + startAngle: datum.arc.startAngle, + endAngle: datum.arc.endAngle, + innerRadius: datum.arc.innerRadius, + outerRadius: datum.arc.outerRadius, + }), + leave: datum => ({ + startAngle: datum.arc.startAngle + (datum.arc.endAngle - datum.arc.startAngle) / 2, + endAngle: datum.arc.startAngle + (datum.arc.endAngle - datum.arc.startAngle) / 2, + innerRadius: datum.arc.innerRadius, + outerRadius: datum.arc.outerRadius, + }), + config: springConfig, + immediate: !animate, + }) + + return { + transition, + interpolate: interpolateArc, + } +} diff --git a/packages/pie/src/Pie.tsx b/packages/pie/src/Pie.tsx index d7e03bc4d..86f1abce8 100644 --- a/packages/pie/src/Pie.tsx +++ b/packages/pie/src/Pie.tsx @@ -16,6 +16,7 @@ import PieLegends from './PieLegends' import { useNormalizedData, usePieFromBox, usePieLayerContext } from './hooks' import { ComputedDatum, PieLayer, PieSvgProps, PieLayerId } from './types' import { defaultProps } from './props' +import { Slices } from './Slices' const Pie = ({ data, @@ -129,24 +130,12 @@ const Pie = ({ if (layers.includes('slices')) { layerById.slices = ( - - {dataWithArc.map(datumWithArc => ( - - key={datumWithArc.id} - datum={datumWithArc} - arcGenerator={arcGenerator} - borderWidth={borderWidth} - borderColor={borderColor(datumWithArc)} - tooltip={tooltip} - isInteractive={isInteractive} - onClick={onClick} - onMouseEnter={onMouseEnter} - onMouseMove={onMouseMove} - onMouseLeave={onMouseLeave} - setActiveId={setActiveId} - /> - ))} - + ) } diff --git a/packages/pie/src/Slices.tsx b/packages/pie/src/Slices.tsx new file mode 100644 index 000000000..9026766ab --- /dev/null +++ b/packages/pie/src/Slices.tsx @@ -0,0 +1,57 @@ +import React from 'react' +import { animated } from 'react-spring' +import { ArcGenerator, useArcsTransition } from '@nivo/arcs' +import { ComputedDatum } from './types' + +/* + + {dataWithArc.map(datumWithArc => ( + + key={datumWithArc.id} + datum={datumWithArc} + arcGenerator={arcGenerator} + borderWidth={borderWidth} + borderColor={borderColor(datumWithArc)} + tooltip={tooltip} + isInteractive={isInteractive} + onClick={onClick} + onMouseEnter={onMouseEnter} + onMouseMove={onMouseMove} + onMouseLeave={onMouseLeave} + setActiveId={setActiveId} + /> + ))} + +) +*/ + +interface SlicesProps { + center: [number, number] + data: ComputedDatum[] + arcGenerator: ArcGenerator +} + +export const Slices = ({ center, data, arcGenerator }: SlicesProps) => { + const { transition, interpolate } = useArcsTransition>(data) + + return ( + + {transition((transitionProps, datum) => { + console.log(transitionProps, datum) + return ( + + ) + })} + + ) +} diff --git a/packages/pie/src/types.ts b/packages/pie/src/types.ts index 76c778d2b..338b168b9 100644 --- a/packages/pie/src/types.ts +++ b/packages/pie/src/types.ts @@ -1,9 +1,8 @@ import * as React from 'react' -import { Arc as ArcGenerator } from 'd3-shape' import { Box, Dimensions, Theme, SvgDefsAndFill } from '@nivo/core' import { OrdinalColorScaleConfig, InheritedColorConfig } from '@nivo/colors' import { LegendProps } from '@nivo/legends' -import { Arc } from '@nivo/arcs' +import { Arc, ArcGenerator } from '@nivo/arcs' export type DatumId = string | number export type DatumValue = number @@ -59,7 +58,7 @@ export type MouseEventHandler = ( event: React.MouseEvent ) => void -export type PieLayerId = 'slices' | 'radialLabels' | 'sliceLabels' | 'legends' +export type PieLayerId = 'radialLabels' | 'slices' | 'sliceLabels' | 'legends' export interface PieCustomLayerProps { dataWithArc: ComputedDatum[] @@ -67,7 +66,7 @@ export interface PieCustomLayerProps { centerY: number radius: number innerRadius: number - arcGenerator: ArcGenerator + arcGenerator: ArcGenerator } export type PieCustomLayer = React.FC>