@@ -6,11 +6,14 @@ interface SpectrogramProps {
6
6
}
7
7
8
8
const Spectrogram : React . FC < SpectrogramProps > = ( { howl } ) => {
9
+ const containerRef = useRef < HTMLDivElement | null > ( null ) ;
9
10
const canvasRef = useRef < HTMLCanvasElement | null > ( null ) ;
10
11
const analyserRef = useRef < AnalyserNode | null > ( null ) ;
11
12
const animationRef = useRef < number | null > ( null ) ;
12
13
const [ isSetup , setIsSetup ] = useState ( false ) ;
13
14
const [ isPlaying , setIsPlaying ] = useState ( false ) ;
15
+ const LEFT_MARGIN = 20 ; // Space for y-axis labels
16
+ const AXIS_RIGHT_PADDING = 30 ; // Space between y-axis labels and graph
14
17
15
18
const setupAudio = useCallback ( ( ) => {
16
19
setIsSetup ( false ) ;
@@ -26,7 +29,6 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
26
29
}
27
30
28
31
analyserRef . current = audioContext . createAnalyser ( ) ;
29
- analyserRef . current . fftSize = 2048 ;
30
32
31
33
const sound = howl as any ;
32
34
if ( ! sound . _sounds || ! sound . _sounds [ 0 ] || ! sound . _sounds [ 0 ] . _node ) {
@@ -66,15 +68,15 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
66
68
67
69
const barWidth = 1 ;
68
70
const height = canvas . height - 20 ;
69
- const leftMargin = 30 ;
71
+ const graphStart = LEFT_MARGIN + AXIS_RIGHT_PADDING ;
70
72
71
73
const imageData = ctx . getImageData (
72
- leftMargin + barWidth ,
74
+ graphStart + barWidth ,
73
75
0 ,
74
- canvas . width - leftMargin - barWidth ,
76
+ canvas . width - graphStart - barWidth ,
75
77
height ,
76
78
) ;
77
- ctx . putImageData ( imageData , leftMargin , 0 ) ;
79
+ ctx . putImageData ( imageData , graphStart , 0 ) ;
78
80
79
81
ctx . clearRect ( canvas . width - barWidth , 0 , barWidth , height ) ;
80
82
@@ -99,22 +101,22 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
99
101
canvas : HTMLCanvasElement ,
100
102
) => {
101
103
ctx . save ( ) ;
102
- ctx . clearRect ( 0 , 0 , 30 , canvas . height ) ;
104
+ ctx . clearRect ( 0 , 0 , LEFT_MARGIN + AXIS_RIGHT_PADDING , canvas . height ) ;
103
105
ctx . clearRect ( 0 , canvas . height - 20 , canvas . width , 20 ) ;
104
106
105
107
ctx . fillStyle = "white" ;
106
- ctx . font = "10px Maven Pro" ;
108
+ ctx . font = "10.5px Maven Pro" ;
107
109
for ( let i = 0 ; i <= 10 ; i ++ ) {
108
110
const freq = ( i / 10 ) * 22.05 ;
109
111
const y = canvas . height - 20 - ( i / 10 ) * ( canvas . height - 20 ) ;
110
- ctx . fillText ( `${ freq . toFixed ( 2 ) } ` , 5 , y ) ;
112
+ ctx . fillText ( `${ freq . toFixed ( 2 ) } k ` , 5 , y ) ;
111
113
}
112
114
113
115
const currentTime = howl . seek ( ) ;
114
116
ctx . fillText (
115
- `${ currentTime . toFixed ( 1 ) } s` ,
116
- canvas . width - 30 ,
117
- canvas . height - 5 ,
117
+ `Time: ${ currentTime . toFixed ( 1 ) } s` ,
118
+ canvas . width / 2 ,
119
+ canvas . height ,
118
120
) ;
119
121
120
122
ctx . restore ( ) ;
@@ -144,6 +146,15 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
144
146
}
145
147
} , [ ] ) ;
146
148
149
+ const resizeCanvas = useCallback ( ( ) => {
150
+ const canvas = canvasRef . current ;
151
+ const container = containerRef . current ;
152
+ if ( canvas && container ) {
153
+ canvas . width = container . clientWidth ;
154
+ canvas . height = container . clientHeight ;
155
+ }
156
+ } , [ ] ) ;
157
+
147
158
useEffect ( ( ) => {
148
159
const initializeSpectrogram = ( ) => {
149
160
if ( howl . state ( ) === "loaded" ) {
@@ -169,6 +180,12 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
169
180
170
181
initializeSpectrogram ( ) ;
171
182
183
+ // Set up ResizeObserver
184
+ const resizeObserver = new ResizeObserver ( resizeCanvas ) ;
185
+ if ( containerRef . current ) {
186
+ resizeObserver . observe ( containerRef . current ) ;
187
+ }
188
+
172
189
return ( ) => {
173
190
stopSpectrogram ( ) ;
174
191
if ( analyserRef . current ) {
@@ -177,17 +194,16 @@ const Spectrogram: React.FC<SpectrogramProps> = ({ howl }) => {
177
194
howl . off ( "play" , handlePlay ) ;
178
195
howl . off ( "pause" , handlePauseOrStop ) ;
179
196
howl . off ( "end" , handlePauseOrStop ) ;
197
+ resizeObserver . disconnect ( ) ;
180
198
} ;
181
- } , [ howl , startSpectrogram , stopSpectrogram ] ) ;
199
+ } , [ howl , startSpectrogram , stopSpectrogram , resizeCanvas ] ) ;
182
200
183
201
return (
184
- < div className = "w-full rounded-xl bg-black p-5" >
185
- < canvas
186
- ref = { canvasRef }
187
- width = "1315"
188
- height = "400"
189
- className = "w-full antialiased"
190
- />
202
+ < div
203
+ ref = { containerRef }
204
+ className = "h-full w-full rounded-xl px-6 pb-8 gradient-mask-r-90"
205
+ >
206
+ < canvas ref = { canvasRef } className = "h-full w-full antialiased" />
191
207
</ div >
192
208
) ;
193
209
} ;
0 commit comments