@@ -18,6 +18,7 @@ import { Config } from "../config/config";
1818import { MassCardController } from "../controller/controller" ;
1919import { MediaBrowser } from "../sections/media-browser" ;
2020import { Icons } from "../const/icons" ;
21+ import { WaAnimation } from "../const/elements" ;
2122
2223class MassNavBar extends LitElement {
2324 private _controller ! : MassCardController ;
@@ -29,8 +30,10 @@ class MassNavBar extends LitElement {
2930 @query ( '#tab-media-browser' ) browserTab ?: HTMLAnchorElement ;
3031 @query ( '#tab-players' ) playersTab ?: HTMLAnchorElement ;
3132 @query ( '#tab-indicator' ) tabIndicator ! : HTMLDivElement ;
33+ @query ( '#animation' ) animationElement ! : WaAnimation ;
3234 @query ( '#navigation' ) navbar ! : HTMLDivElement ;
3335 private animationLength = 350 ;
36+ private animating = false ;
3437
3538 @consume ( { context : activeSectionContext , subscribe : true } )
3639 @state ( )
@@ -89,21 +92,29 @@ class MassNavBar extends LitElement {
8992 }
9093 return elems [ section ] ;
9194 }
92- private animateBounceLeft ( to_element : HTMLAnchorElement ) : Keyframe {
95+ private animateBounceLeft ( from_element : HTMLAnchorElement , to_element : HTMLAnchorElement ) : Keyframe {
96+ const from_left = from_element . offsetLeft ;
97+ const from_width = from_element . offsetWidth ;
98+
9399 const to_left = to_element . offsetLeft ;
94100 const to_width = to_element . offsetWidth ;
95101
96102 const bounce_move = to_width * 0.2 ;
97103
98104 const bounce_left = Math . max ( 0 , to_left - bounce_move ) ;
99105 const bounce_width = bounce_left > 0 ? to_width : to_width - ( to_left + bounce_move )
106+ const translate_x = bounce_left - from_left ;
107+ const scale_x = bounce_width / from_width ;
108+
100109 return {
101- left : `${ bounce_left . toString ( ) } px` ,
102- width : `${ bounce_width . toString ( ) } px` ,
110+ transform : `translateX(${ translate_x . toString ( ) } px) scaleX(${ scale_x . toString ( ) } )` ,
103111 offset : 0.8 ,
104112 }
105113 }
106- private animateBounceRight ( to_element : HTMLAnchorElement ) : Keyframe {
114+ private animateBounceRight ( from_element : HTMLAnchorElement , to_element : HTMLAnchorElement ) : Keyframe {
115+ const from_left = from_element . offsetLeft ;
116+ const from_width = from_element . offsetWidth ;
117+
107118 const to_left = to_element . offsetLeft ;
108119 const to_width = to_element . offsetWidth ;
109120
@@ -113,13 +124,15 @@ class MassNavBar extends LitElement {
113124
114125 const bounce_left = to_left + bounce_move ;
115126 const bounce_width = to_elem_x_end >= navbarWidth ? navbarWidth - bounce_left : to_width ;
127+ const translate_x = bounce_left - from_left ;
128+ const scale_x = bounce_width / from_width ;
116129 return {
117- left : `${ bounce_left . toString ( ) } px` ,
118- width : `${ bounce_width . toString ( ) } px` ,
130+ transform : `translateX(${ translate_x . toString ( ) } px) scaleX(${ scale_x . toString ( ) } )` ,
119131 offset : 0.8 ,
120132 }
121133 }
122134 private animateTabChange ( from_section : Sections , to_section : Sections ) {
135+ this . animating = true ;
123136 if ( from_section == to_section ) {
124137 return ;
125138 }
@@ -132,31 +145,30 @@ class MassNavBar extends LitElement {
132145 const from_left = from_elem . offsetLeft ;
133146 const to_width = to_elem . offsetWidth ;
134147 const to_left = to_elem . offsetLeft ;
135- const bounce = from_left - to_left > 0 ? this . animateBounceLeft ( to_elem ) : this . animateBounceRight ( to_elem )
148+ const bounce = ( from_left - to_left > 0 )
149+ ? this . animateBounceLeft ( from_elem , to_elem )
150+ : this . animateBounceRight ( from_elem , to_elem )
151+
152+ const translate_x = to_left - from_left ;
153+ const scale_x = to_width / from_width ;
154+
136155 const _keyframes = [
137- {
138- left : `${ from_left . toString ( ) } px` ,
139- width : `${ from_width . toString ( ) } px`
140- } , // from
141156 bounce ,
142157 {
143- left : `${ to_left . toString ( ) } px` ,
144- width : `${ to_width . toString ( ) } px`
145- } , // to
158+ transform : `translateX(${ translate_x . toString ( ) } px) scaleX(${ scale_x . toString ( ) } )` ,
159+ }
146160 ]
147- const keyframeEffect = new KeyframeEffect (
148- this . tabIndicator ,
149- _keyframes ,
150- {
151- // keyframe options
152- duration : this . animationLength ,
153- // direction: "alternate",
154- // easing: "ease-in-out",
155- iterations : 1 ,
156- } ,
157- ) ;
158- const animation = new Animation ( keyframeEffect , document . timeline ) ;
159- animation . play ( ) ;
161+ const animation = this . animationElement ;
162+ animation . keyframes = _keyframes ;
163+ animation . addEventListener (
164+ 'wa-finish' ,
165+ ( ) => {
166+ this . animating = false ;
167+ this . tabIndicator . style . left = `${ to_left . toString ( ) } px` ;
168+ this . tabIndicator . style . width = `${ to_width . toString ( ) } px` ;
169+ }
170+ )
171+ animation . play = true ;
160172 }
161173
162174 protected renderMusicPlayerTab ( ) : TemplateResult {
@@ -191,17 +203,6 @@ class MassNavBar extends LitElement {
191203 }
192204 return html `` ;
193205 }
194- private renderIndicator ( ) : TemplateResult {
195- const elem = this . getSectionElement ( this . active_section ) ;
196- const left = elem ? elem . offsetLeft : 0 ;
197- const width = elem ? elem . offsetWidth : 113 ;
198- return html `
199- < div
200- id ="tab-indicator "
201- style ="left: ${ left } px; width: ${ width } px "
202- > </ div >
203- `
204- }
205206 private renderTab ( section : Sections , icon : string ) : TemplateResult {
206207 const active = this . active_section == section ;
207208 return html `
@@ -231,7 +232,6 @@ class MassNavBar extends LitElement {
231232 />
232233 ${ this . renderMusicPlayerTab ( ) } ${ this . renderQueueTab ( ) }
233234 ${ this . renderMediaBrowserTab ( ) } ${ this . renderPlayersTab ( ) }
234- ${ this . renderIndicator ( ) }
235235 </ nav >
236236 </ div >
237237 ` ;
@@ -242,6 +242,22 @@ class MassNavBar extends LitElement {
242242 }
243243 return _changedProperties . size > 0 ;
244244 }
245+ protected firstUpdated ( ) : void {
246+ if ( ! this . tabIndicator ) {
247+ const indicator = document . createElement ( 'div' ) ;
248+ indicator . id = 'tab-indicator' ;
249+ const elem = this . getSectionElement ( this . active_section ) ;
250+ const left = elem ?. offsetLeft ?? 0 ;
251+ indicator . style = `left: ${ left . toString ( ) } px;`
252+
253+ const animation = document . createElement ( 'wa-animation' ) as WaAnimation ;
254+ animation . id = 'animation'
255+ animation . duration = this . animationLength ;
256+ animation . iterations = 1 ;
257+ animation . appendChild ( indicator )
258+ this . navbar . appendChild ( animation )
259+ }
260+ }
245261 static get styles ( ) : CSSResultGroup {
246262 return styles ;
247263 }
0 commit comments