Skip to content

Commit

Permalink
feat(arcs): add configurable transition modes
Browse files Browse the repository at this point in the history
  • Loading branch information
plouc committed Dec 18, 2020
1 parent 5dbbe0c commit e76747d
Showing 1 changed file with 128 additions and 31 deletions.
159 changes: 128 additions & 31 deletions packages/arcs/src/motion.ts
Expand Up @@ -27,6 +27,123 @@ export const interpolateArc = (
}
)

interface TransitionModeConfig {
enter: (arc: Arc) => Arc
update: (arc: Arc) => Arc
leave: (arc: Arc) => Arc
}

const transitionModeStartAngle = {
enter: (arc: Arc) => ({
...arc,
endAngle: arc.startAngle,
}),
update: (arc: Arc) => arc,
leave: (arc: Arc) => ({
...arc,
startAngle: arc.endAngle,
}),
}

const transitionModeMiddleAngle = {
enter: (arc: Arc) => {
const middleAngle = arc.startAngle + (arc.endAngle - arc.startAngle) / 2

return {
...arc,
startAngle: middleAngle,
endAngle: middleAngle,
}
},
update: (arc: Arc) => arc,
leave: (arc: Arc) => {
const middleAngle = arc.startAngle + (arc.endAngle - arc.startAngle) / 2

return {
...arc,
startAngle: middleAngle,
endAngle: middleAngle,
}
},
}

const transitionModeEndAngle = {
enter: (arc: Arc) => ({
...arc,
startAngle: arc.endAngle,
}),
update: (arc: Arc) => arc,
leave: (arc: Arc) => ({
...arc,
endAngle: arc.startAngle,
}),
}

const transitionModeInnerRadius = {
enter: (arc: Arc) => ({
...arc,
outerRadius: arc.innerRadius,
}),
update: (arc: Arc) => arc,
leave: (arc: Arc) => ({
...arc,
innerRadius: arc.outerRadius,
}),
}

const transitionModeCenterRadius = {
enter: (arc: Arc) => {
const centerRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) / 2

return {
...arc,
innerRadius: centerRadius,
outerRadius: centerRadius,
}
},
update: (arc: Arc) => arc,
leave: (arc: Arc) => {
const centerRadius = arc.innerRadius + (arc.outerRadius - arc.innerRadius) / 2

return {
...arc,
innerRadius: centerRadius,
outerRadius: centerRadius,
}
},
}

const transitionModeOuterRadius = {
enter: (arc: Arc) => ({
...arc,
innerRadius: arc.outerRadius,
}),
update: (arc: Arc) => arc,
leave: (arc: Arc) => ({
...arc,
outerRadius: arc.innerRadius,
}),
}

export const transitionModes = [
'startAngle',
'middleAngle',
'endAngle',
'innerRadius',
'centerRadius',
'outerRadius',
] as const
export type TransitionMode = typeof transitionModes[number]

const transitionModeById: Record<TransitionMode, TransitionModeConfig> = {
startAngle: transitionModeStartAngle,
middleAngle: transitionModeMiddleAngle,
endAngle: transitionModeEndAngle,
innerRadius: transitionModeInnerRadius,
centerRadius: transitionModeCenterRadius,
outerRadius: transitionModeOuterRadius,
}

/**
* This hook can be used to animate a single arc,
* if you want to animate a group of arcs,
Expand Down Expand Up @@ -61,9 +178,14 @@ export const useAnimatedArc = (datumWithArc: { arc: Arc }, arcGenerator: ArcGene
* if you want to animate a single arc,
* please have a look at the `useAnimatedArc` hook.
*/
export const useArcsTransition = <Datum extends DatumWithArc>(data: Datum[]) => {
export const useArcsTransition = <Datum extends DatumWithArc>(
data: Datum[],
mode: TransitionMode = 'innerRadius'
) => {
const { animate, config: springConfig } = useMotionConfig()

const transitionMode = transitionModeById[mode]

const transition = useTransition<
Datum,
{
Expand All @@ -74,36 +196,11 @@ export const useArcsTransition = <Datum extends DatumWithArc>(data: Datum[]) =>
}
>(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,
}),
initial: datum => transitionMode.update(datum.arc),
from: datum => transitionMode.enter(datum.arc),
enter: datum => transitionMode.update(datum.arc),
update: datum => transitionMode.update(datum.arc),
leave: datum => transitionMode.leave(datum.arc),
config: springConfig,
immediate: !animate,
})
Expand Down

0 comments on commit e76747d

Please sign in to comment.