-
Notifications
You must be signed in to change notification settings - Fork 2
/
AnimatedNodes.tsx
101 lines (95 loc) · 2.54 KB
/
AnimatedNodes.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import React from 'react';
import { useTransition, animated } from 'react-spring';
import { findCollapsedParent, translateCoords } from './utils/treeUtils';
import { TreeLayout, TreeOrientation } from './Tree';
export type AnimatedNodesProps = {
nodes: any[];
nodeId: (node: any) => number | string;
layout?: TreeLayout;
orientation?: TreeOrientation;
renderNode: (node: any, onClick: () => any) => React.ReactNode;
onNodeClick: (node: any) => any;
};
function AnimatedNodes(props: AnimatedNodesProps) {
const { nodes, nodeId, renderNode, onNodeClick } = props;
const transitions = useTransition<
any,
any /*{ xy: number[], opacity: number}*/
>(nodes, (node) => nodeId(node.data), {
// config: { tension: 1000, friction: 130, mass: 5 },
from: (node) => {
const { x, y } = translateCoords(
node.parent || { x: 0, y: 0 },
props.layout,
props.orientation
);
return {
xy: [x, y],
opacity: 0,
};
},
enter: (node) => {
const { x, y } = translateCoords(node, props.layout, props.orientation);
return {
xy: [x, y],
opacity: 1,
};
},
update: (node) => {
const { x, y } = translateCoords(node, props.layout, props.orientation);
return {
xy: [x, y],
opacity: 1,
};
},
leave: (node) => {
if (node.parent) {
// child leaving
const collapsedParent = findCollapsedParent(node.parent);
const { x, y } = translateCoords(
{
x: collapsedParent
? collapsedParent.data.x0 ?? collapsedParent.x
: 0,
y: collapsedParent
? collapsedParent.data.y0 ?? collapsedParent.y
: 0,
},
props.layout,
props.orientation
);
return {
xy: [x, y],
opacity: 0,
};
} else {
// root node leaving (new tree likely)
const { x, y } = translateCoords(
{ x: 0, y: 0 },
props.layout,
props.orientation
);
return {
xy: [x, y],
opacity: 0,
};
}
},
});
return (
<>
{transitions.map(({ item, props, key }) => (
<animated.g
opacity={props.opacity}
transform={props.xy.interpolate(
(x: number, y: number) => `translate(${x}, ${y})`
)}
key={key}
>
{renderNode(item, () => onNodeClick(item))}
</animated.g>
))}
</>
);
}
export default AnimatedNodes;