11import "./style.scss" ;
2+ import Ref from "html-tag-js/ref" ;
23
34export default class AudioPlayer {
45 constructor ( container ) {
56 this . container = container ;
67 this . audio = new Audio ( ) ;
78 this . isPlaying = false ;
9+ this . elements = {
10+ playBtn : new Ref ( ) ,
11+ playIcon : new Ref ( ) ,
12+ timeline : new Ref ( ) ,
13+ progress : new Ref ( ) ,
14+ progressHandle : new Ref ( ) ,
15+ timeDisplay : new Ref ( ) ,
16+ duration : new Ref ( ) ,
17+ volumeBtn : new Ref ( ) ,
18+ } ;
819 this . initializeUI ( ) ;
920 this . initializeEvents ( ) ;
1021 this . cleanup = this . cleanup . bind ( this ) ;
1122 }
1223
1324 initializeUI ( ) {
14- const auidoPlayer = (
25+ const audioPlayer = (
1526 < div className = "audio-player" >
16- < button className = "play-btn" ariaLabel = "Play/Pause" >
17- < span className = "icon play_arrow" > </ span >
27+ < button
28+ ref = { this . elements . playBtn }
29+ className = "play-btn"
30+ ariaLabel = "Play/Pause"
31+ >
32+ < span ref = { this . elements . playIcon } className = "icon play_arrow" > </ span >
1833 </ button >
1934
20- < div className = "timeline" >
21- < div className = "progress" > </ div >
22- < div className = "progress-handle" > </ div >
35+ < div ref = { this . elements . timeline } className = "timeline" >
36+ < div ref = { this . elements . progress } className = "progress" > </ div >
37+ < div
38+ ref = { this . elements . progressHandle }
39+ className = "progress-handle"
40+ > </ div >
2341 </ div >
2442
25- < div className = "time" > 0:00</ div >
43+ < div ref = { this . elements . timeDisplay } className = "time" >
44+ 0:00
45+ </ div >
2646
2747 < div className = "volume-control" >
28- < button className = "volume-btn" ariaLabel = "Volume" > </ button >
48+ < button
49+ ref = { this . elements . volumeBtn }
50+ className = "volume-btn"
51+ ariaLabel = "Volume"
52+ > </ button >
2953 </ div >
3054 </ div >
3155 ) ;
3256
33- this . container . appendChild ( auidoPlayer ) ;
57+ this . container . appendChild ( audioPlayer ) ;
3458
35- this . elements = {
36- playBtn : this . container . querySelector ( ".play-btn" ) ,
37- playIcon : this . container . querySelector ( ".play-btn .icon" ) ,
38- timeline : this . container . querySelector ( ".timeline" ) ,
39- progress : this . container . querySelector ( ".progress" ) ,
40- progressHandle : this . container . querySelector ( ".progress-handle" ) ,
41- timeDisplay : this . container . querySelector ( ".time" ) ,
42- duration : this . container . querySelector ( ".duration" ) ,
43- volumeBtn : this . container . querySelector ( ".volume-btn" ) ,
44- } ;
45- this . elements . volumeBtn . innerHTML = `<svg viewBox="0 0 24 24">
46- <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>
47- </svg>` ;
59+ this . elements . volumeBtn . el . innerHTML = `<svg viewBox="0 0 24 24">
60+ <path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/>
61+ </svg>` ;
4862 }
4963
5064 initializeEvents ( ) {
5165 // Play/Pause
52- this . elements . playBtn . addEventListener ( "click" , ( ) => this . togglePlay ( ) ) ;
66+ this . elements . playBtn . el . addEventListener ( "click" , ( ) => this . togglePlay ( ) ) ;
5367
5468 // Timeline
55- this . elements . timeline . addEventListener ( "click" , ( e ) => this . seek ( e ) ) ;
56- this . elements . timeline . addEventListener ( "touchstart" , ( e ) => this . seek ( e ) ) ;
69+ this . elements . timeline . el . addEventListener ( "click" , ( e ) => this . seek ( e ) ) ;
70+ this . elements . timeline . el . addEventListener ( "touchstart" , ( e ) =>
71+ this . seek ( e ) ,
72+ ) ;
5773
5874 // Volume
59- this . elements . volumeBtn . addEventListener ( "click" , ( ) => this . toggleMute ( ) ) ;
75+ this . elements . volumeBtn . el . addEventListener ( "click" , ( ) =>
76+ this . toggleMute ( ) ,
77+ ) ;
6078
6179 // Audio events
6280 this . audio . addEventListener ( "timeupdate" , ( ) => this . updateProgress ( ) ) ;
@@ -66,18 +84,18 @@ export default class AudioPlayer {
6684 togglePlay ( ) {
6785 if ( this . isPlaying ) {
6886 this . audio . pause ( ) ;
69- this . elements . playIcon . classList . remove ( "pause" ) ;
70- this . elements . playIcon . classList . add ( "play_arrow" ) ;
87+ this . elements . playIcon . el . classList . remove ( "pause" ) ;
88+ this . elements . playIcon . el . classList . add ( "play_arrow" ) ;
7189 } else {
7290 this . audio . play ( ) ;
73- this . elements . playIcon . classList . remove ( "play_arrow" ) ;
74- this . elements . playIcon . classList . add ( "pause" ) ;
91+ this . elements . playIcon . el . classList . remove ( "play_arrow" ) ;
92+ this . elements . playIcon . el . classList . add ( "pause" ) ;
7593 }
7694 this . isPlaying = ! this . isPlaying ;
7795 }
7896
7997 seek ( e ) {
80- const rect = this . elements . timeline . getBoundingClientRect ( ) ;
98+ const rect = this . elements . timeline . el . getBoundingClientRect ( ) ;
8199 const pos =
82100 ( e . type . includes ( "touch" ) ? e . touches [ 0 ] . clientX : e . clientX ) - rect . left ;
83101 const percentage = pos / rect . width ;
@@ -86,9 +104,9 @@ export default class AudioPlayer {
86104
87105 updateProgress ( ) {
88106 const percentage = ( this . audio . currentTime / this . audio . duration ) * 100 ;
89- this . elements . progress . style . width = `${ percentage } %` ;
90- this . elements . progressHandle . style . left = `${ percentage } %` ;
91- this . elements . timeDisplay . textContent = this . formatTime (
107+ this . elements . progress . el . style . width = `${ percentage } %` ;
108+ this . elements . progressHandle . el . style . left = `${ percentage } %` ;
109+ this . elements . timeDisplay . el . textContent = this . formatTime (
92110 this . audio . currentTime ,
93111 ) ;
94112 }
@@ -102,18 +120,18 @@ export default class AudioPlayer {
102120 toggleMute ( ) {
103121 this . audio . muted = ! this . audio . muted ;
104122 if ( this . audio . muted ) {
105- this . elements . volumeBtn . innerHTML =
123+ this . elements . volumeBtn . el . innerHTML =
106124 '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z"/></svg>' ;
107125 } else {
108- this . elements . volumeBtn . innerHTML =
126+ this . elements . volumeBtn . el . innerHTML =
109127 '<svg viewBox="0 0 24 24"><path d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02z"/></svg>' ;
110128 }
111129 }
112130
113131 audioEnded ( ) {
114132 this . isPlaying = false ;
115- this . elements . playIcon . classList . remove ( "pause" ) ;
116- this . elements . playIcon . classList . add ( "play_arrow" ) ;
133+ this . elements . playIcon . el . classList . remove ( "pause" ) ;
134+ this . elements . playIcon . el . classList . add ( "play_arrow" ) ;
117135 }
118136
119137 loadTrack ( src ) {
@@ -126,12 +144,14 @@ export default class AudioPlayer {
126144 this . audio . currentTime = 0 ;
127145 this . isPlaying = false ;
128146
129- this . elements . playBtn . removeEventListener ( "click" , ( ) => this . togglePlay ( ) ) ;
130- this . elements . timeline . removeEventListener ( "click" , ( e ) => this . seek ( e ) ) ;
131- this . elements . timeline . removeEventListener ( "touchstart" , ( e ) =>
147+ this . elements . playBtn . el . removeEventListener ( "click" , ( ) =>
148+ this . togglePlay ( ) ,
149+ ) ;
150+ this . elements . timeline . el . removeEventListener ( "click" , ( e ) => this . seek ( e ) ) ;
151+ this . elements . timeline . el . removeEventListener ( "touchstart" , ( e ) =>
132152 this . seek ( e ) ,
133153 ) ;
134- this . elements . volumeBtn . removeEventListener ( "click" , ( ) =>
154+ this . elements . volumeBtn . el . removeEventListener ( "click" , ( ) =>
135155 this . toggleMute ( ) ,
136156 ) ;
137157 this . audio . removeEventListener ( "timeupdate" , ( ) => this . updateProgress ( ) ) ;
0 commit comments