@@ -35,118 +35,57 @@ function SmoothLines({
3535 prevFocus,
3636 nextFocus,
3737 center,
38- minZoom = 0 ,
38+ minZoom = 0 , // TODO use minZoom
3939 maxZoom = 1.2 ,
4040} : Props ) {
4141 const lines = useLineTransitions ( prevLines , nextLines )
4242
4343 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 )
5245 : lineWidth
5346
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-
13747 const prevFocusKeys = prevFocus . map (
13848 index => prevLines [ index ] ?. key
13949 )
14050 const nextFocusKeys = nextFocus . map (
14151 index => nextLines [ index ] ?. key
14252 )
14353
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+
14483 return (
14584 < Container
14685 width = { containerWidth }
14786 height = { containerHeight }
14887 >
149- < Content dx = { left } dy = { dy } scale = { zoom } >
88+ < Content dx = { dx } dy = { dy } scale = { zoom } >
15089 < Lines
15190 lines = { lines }
15291 prevFocusKeys = { prevFocusKeys }
@@ -160,21 +99,57 @@ function SmoothLines({
16099 )
161100}
162101
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
177131 )
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
178153}
179154
180155function Container ( {
@@ -224,6 +199,22 @@ function Content({
224199 )
225200}
226201
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+
227218function clamp ( num : number , min : number , max : number ) {
228219 return num <= min ? min : num >= max ? max : num
229220}
0 commit comments