@@ -35,118 +35,57 @@ function SmoothLines({
35
35
prevFocus,
36
36
nextFocus,
37
37
center,
38
- minZoom = 0 ,
38
+ minZoom = 0 , // TODO use minZoom
39
39
maxZoom = 1.2 ,
40
40
} : Props ) {
41
41
const lines = useLineTransitions ( prevLines , nextLines )
42
42
43
43
const focusWidth = Array . isArray ( lineWidth )
44
- ? tween (
45
- {
46
- fixed : false ,
47
- interval : [ 0 , 1 ] ,
48
- extremes : lineWidth ,
49
- } ,
50
- progress
51
- )
44
+ ? tweenProp ( lineWidth [ 0 ] , lineWidth [ 1 ] , progress )
52
45
: lineWidth
53
46
54
- const prevExtremes = [
55
- Math . min ( ...prevFocus ) ,
56
- Math . max ( ...prevFocus ) ,
57
- ]
58
- const nextExtremes = [
59
- Math . min ( ...nextFocus ) ,
60
- Math . max ( ...nextFocus ) ,
61
- ]
62
- const prevFocusHeight =
63
- prevExtremes [ 1 ] - prevExtremes [ 0 ] + 3
64
- const nextFocusHeight =
65
- nextExtremes [ 1 ] - nextExtremes [ 0 ] + 3
66
- const focusHeight =
67
- tween (
68
- {
69
- fixed : false ,
70
- interval : [ 0 , 1 ] ,
71
- extremes : [ prevFocusHeight , nextFocusHeight ] ,
72
- ease : easing . easeInOutCubic ,
73
- } ,
74
- progress
75
- ) * lineHeight
76
-
77
- const zoom = Math . min (
78
- containerWidth / focusWidth ,
79
- containerHeight / focusHeight ,
80
- maxZoom
81
- )
82
-
83
- const contentHeight =
84
- tween (
85
- {
86
- fixed : false ,
87
- interval : [ 0 , 1 ] ,
88
- extremes : [ prevLines . length , nextLines . length ] ,
89
- ease : easing . easeInOutCubic ,
90
- } ,
91
- progress
92
- ) *
93
- lineHeight *
94
- zoom
95
- const focusStart =
96
- tween (
97
- {
98
- fixed : false ,
99
- interval : [ 0 , 1 ] ,
100
- extremes : [
101
- prevExtremes [ 0 ] - 1 ,
102
- nextExtremes [ 0 ] - 1 ,
103
- ] ,
104
- ease : easing . easeInOutCubic ,
105
- } ,
106
- progress
107
- ) *
108
- lineHeight *
109
- zoom
110
- const focusEnd =
111
- tween (
112
- {
113
- fixed : false ,
114
- interval : [ 0 , 1 ] ,
115
- extremes : [
116
- prevExtremes [ 1 ] + 2 ,
117
- nextExtremes [ 1 ] + 2 ,
118
- ] ,
119
- ease : easing . easeInOutCubic ,
120
- } ,
121
- progress
122
- ) *
123
- lineHeight *
124
- zoom
125
-
126
- const dy = getDY (
127
- containerHeight ,
128
- contentHeight ,
129
- focusStart ,
130
- focusEnd
131
- )
132
-
133
- const left = center
134
- ? containerWidth / 2 - ( focusWidth * zoom ) / 2
135
- : 0
136
-
137
47
const prevFocusKeys = prevFocus . map (
138
48
index => prevLines [ index ] ?. key
139
49
)
140
50
const nextFocusKeys = nextFocus . map (
141
51
index => nextLines [ index ] ?. key
142
52
)
143
53
54
+ const [ prevZoom , prevDX , prevDY ] = getContentProps ( {
55
+ containerWidth,
56
+ containerHeight,
57
+ lineWidth : Array . isArray ( lineWidth )
58
+ ? lineWidth [ 0 ]
59
+ : lineWidth ,
60
+ lineHeight,
61
+ maxZoom,
62
+ horizontalCenter : ! ! center ,
63
+ focusLineIndexList : prevFocus ,
64
+ originalContentHeight : prevLines . length * lineHeight ,
65
+ } )
66
+ const [ nextZoom , nextDX , nextDY ] = getContentProps ( {
67
+ containerWidth,
68
+ containerHeight,
69
+ lineWidth : Array . isArray ( lineWidth )
70
+ ? lineWidth [ 1 ]
71
+ : lineWidth ,
72
+ lineHeight,
73
+ maxZoom,
74
+ horizontalCenter : ! ! center ,
75
+ focusLineIndexList : nextFocus ,
76
+ originalContentHeight : nextLines . length * lineHeight ,
77
+ } )
78
+
79
+ const zoom = tweenProp ( prevZoom , nextZoom , progress )
80
+ const dx = tweenProp ( prevDX , nextDX , progress )
81
+ const dy = tweenProp ( prevDY , nextDY , progress )
82
+
144
83
return (
145
84
< Container
146
85
width = { containerWidth }
147
86
height = { containerHeight }
148
87
>
149
- < Content dx = { left } dy = { dy } scale = { zoom } >
88
+ < Content dx = { dx } dy = { dy } scale = { zoom } >
150
89
< Lines
151
90
lines = { lines }
152
91
prevFocusKeys = { prevFocusKeys }
@@ -160,21 +99,57 @@ function SmoothLines({
160
99
)
161
100
}
162
101
163
- function getDY (
164
- containerHeight : number ,
165
- contentHeight : number ,
166
- focusStart : number ,
167
- focusEnd : number
168
- ) {
169
- if ( containerHeight > contentHeight ) {
170
- return ( containerHeight - contentHeight ) / 2
171
- }
172
- const focusCenter = ( focusEnd + focusStart ) / 2
173
- return clamp (
174
- containerHeight / 2 - focusCenter ,
175
- containerHeight - contentHeight ,
176
- 0
102
+ function getContentProps ( {
103
+ containerWidth,
104
+ containerHeight,
105
+ lineWidth,
106
+ lineHeight,
107
+ maxZoom,
108
+ focusLineIndexList,
109
+ originalContentHeight,
110
+ horizontalCenter,
111
+ } : {
112
+ containerWidth : number
113
+ containerHeight : number
114
+ lineWidth : number
115
+ lineHeight : number
116
+ maxZoom : number
117
+ focusLineIndexList : number [ ]
118
+ originalContentHeight : number
119
+ horizontalCenter : boolean
120
+ } ) {
121
+ const extremes = [
122
+ Math . min ( ...focusLineIndexList ) ,
123
+ Math . max ( ...focusLineIndexList ) ,
124
+ ]
125
+ const originalFocusHeight =
126
+ ( extremes [ 1 ] - extremes [ 0 ] + 3 ) * lineHeight
127
+ const zoom = Math . min (
128
+ containerWidth / lineWidth ,
129
+ containerHeight / originalFocusHeight ,
130
+ maxZoom
177
131
)
132
+
133
+ const contentHeight = originalContentHeight * zoom
134
+
135
+ const focusStart = ( extremes [ 0 ] - 1 ) * lineHeight * zoom
136
+ const focusEnd = ( extremes [ 1 ] + 2 ) * lineHeight * zoom
137
+ const focusCenter = ( focusEnd + focusStart ) / 2
138
+
139
+ const dy =
140
+ containerHeight > contentHeight
141
+ ? ( containerHeight - contentHeight ) / 2
142
+ : clamp (
143
+ containerHeight / 2 - focusCenter ,
144
+ containerHeight - contentHeight ,
145
+ 0
146
+ )
147
+
148
+ const dx = horizontalCenter
149
+ ? containerWidth / 2 - ( lineWidth * zoom ) / 2
150
+ : 0
151
+
152
+ return [ zoom , dx , dy ] as const
178
153
}
179
154
180
155
function Container ( {
@@ -224,6 +199,22 @@ function Content({
224
199
)
225
200
}
226
201
202
+ function tweenProp (
203
+ start : number ,
204
+ end : number ,
205
+ progress : number
206
+ ) {
207
+ return tween (
208
+ {
209
+ fixed : false ,
210
+ interval : [ 0 , 1 ] ,
211
+ extremes : [ start , end ] ,
212
+ ease : easing . easeInOutCubic ,
213
+ } ,
214
+ progress
215
+ )
216
+ }
217
+
227
218
function clamp ( num : number , min : number , max : number ) {
228
219
return num <= min ? min : num >= max ? max : num
229
220
}
0 commit comments