1
1
import React from 'react' ;
2
2
import PropTypes from 'prop-types' ;
3
3
4
- export default class Visualizer extends React . Component {
4
+ export default class Visualizer extends React . PureComponent {
5
+ rafId = null ;
6
+ timerId = null ;
7
+
5
8
constructor ( props ) {
6
9
super ( props ) ;
7
10
this . state = {
@@ -14,16 +17,17 @@ export default class Visualizer extends React.Component {
14
17
} ;
15
18
}
16
19
17
- // In order to get around some mobile browser limitations,
18
- // we can only generate a lot
19
- // of the audio context stuff AFTER the audio has been triggered.
20
- // We can't see it until
21
- // then anyway so it makes no difference to desktop.
22
- componentWillReceiveProps ( nextProps ) {
23
- if ( nextProps . playing && ! this . state . eq . context ) {
24
- this . initiateEQ ( ) ;
25
- this . createVisualizer ( ) ;
26
- }
20
+ componentDidMount ( ) {
21
+ this . initiateEQ ( ) ;
22
+ this . createVisualizer ( ) ;
23
+ this . startDrawing ( ) ;
24
+ }
25
+
26
+ componentWillUnmount ( ) {
27
+ this . stopDrawing ( ) ;
28
+ this . state . eq . analyser . disconnect ( ) ;
29
+ this . state . eq . src . disconnect ( ) ;
30
+ this . state . eq . context . close ( ) ;
27
31
}
28
32
29
33
initiateEQ ( ) {
@@ -47,7 +51,6 @@ export default class Visualizer extends React.Component {
47
51
eq . bands = new Uint8Array ( eq . analyser . frequencyBinCount - 32 ) ;
48
52
49
53
this . setState ( { eq } ) ;
50
- this . updateEQBands ( ) ;
51
54
}
52
55
53
56
/** *
@@ -56,11 +59,11 @@ export default class Visualizer extends React.Component {
56
59
* visualizer is up to date.
57
60
*/
58
61
updateEQBands ( ) {
62
+ const newEQ = this . state . eq ;
59
63
// Populate the buffer with the audio source’s current data
60
- this . state . eq . analyser . getByteFrequencyData ( this . state . eq . bands ) ;
64
+ newEQ . analyser . getByteFrequencyData ( newEQ . bands ) ;
61
65
62
- // Can’t stop, won’t stop
63
- requestAnimationFrame ( ( ) => this . updateEQBands ( ) ) ;
66
+ this . setState ( { eq : { ...newEQ } } ) ;
64
67
}
65
68
66
69
/** *
@@ -77,22 +80,41 @@ export default class Visualizer extends React.Component {
77
80
width : this . _canvas . width ,
78
81
barWidth : this . _canvas . width / this . state . eq . bands . length
79
82
} ;
83
+ }
80
84
85
+ startDrawing = ( ) => {
86
+ if ( ! this . rafId ) {
87
+ this . rafId = window . requestAnimationFrame ( this . drawingLoop ) ;
88
+ }
89
+ } ;
90
+
91
+ stopDrawing = ( ) => {
92
+ window . cancelAnimationFrame ( this . rafId ) ;
93
+ clearTimeout ( this . timerId ) ;
94
+ } ;
95
+
96
+ drawingLoop = ( ) => {
97
+ const haveWaveform = this . state . eq . bands . reduce ( ( a , b ) => a + b , 0 ) !== 0 ;
98
+
99
+ this . updateEQBands ( ) ;
81
100
this . drawVisualizer ( ) ;
82
- }
101
+
102
+ // Because timeupdate events are not triggered at browser speed,
103
+ // we use requestanimationframe for higher framerates
104
+ if ( haveWaveform ) {
105
+ this . rafId = window . requestAnimationFrame ( this . drawingLoop ) ;
106
+ }
107
+ // If there is no music or audio in the song, then reduce the FPS
108
+ else {
109
+ this . timerId = setTimeout ( this . drawingLoop , 250 ) ;
110
+ }
111
+ } ;
83
112
84
113
/** *
85
114
* As a base visualizer, the equalizer bands are drawn using
86
115
* canvas in the window directly above the song into.
87
116
*/
88
117
drawVisualizer ( ) {
89
- if ( this . state . eq . bands . reduce ( ( a , b ) => a + b , 0 ) !== 0 )
90
- requestAnimationFrame ( ( ) => this . drawVisualizer ( ) ) ;
91
- // Because timeupdate events are not triggered at browser speed,
92
- // we use requestanimationframe for higher framerates
93
- // eslint-disable-next-line no-inline-comments
94
- // If there is no music or audio in the song, then reduce the FPS
95
- else setTimeout ( ( ) => this . drawVisualizer ( ) , 250 ) ;
96
118
// Intial bar x coordinate
97
119
let y ,
98
120
x = 0 ;
@@ -139,6 +161,5 @@ export default class Visualizer extends React.Component {
139
161
}
140
162
141
163
Visualizer . propTypes = {
142
- player : PropTypes . object ,
143
- playing : PropTypes . bool
164
+ player : PropTypes . object
144
165
} ;
0 commit comments