33 * @author xxx
44 */
55
6+ import 'hacktimer' ;
7+
68interface cameraOption {
79 width ?: number ;
810 height ?: number ;
911 mirror ?: boolean ;
12+ enableOnInactiveState ?: boolean ;
1013 targetCanvas ?: HTMLCanvasElement ;
1114 onSuccess ?: ( ) => void ;
1215 onError ?: ( ) => void ;
@@ -15,7 +18,6 @@ interface cameraOption {
1518 switchError ?: ( ) => void ;
1619 videoLoaded ?: ( ) => void ;
1720}
18-
1921export default class Camera {
2022 constructor ( videoElement : HTMLVideoElement , opt : Partial < cameraOption > = { } ) {
2123 this . video = videoElement ;
@@ -24,13 +26,14 @@ export default class Camera {
2426 this . visible = true ;
2527 this . isCameraRunning = true ;
2628 this . initVideoStream ( ) ;
27- this . registerVisiblityEvent ( ) ;
29+ this . options . enableOnInactiveState && this . registerVisiblityEvent ( ) ;
2830 }
2931
3032 private noop = ( ) => { } ;
3133 /** 默认配置对象 */
3234 private defaultOption : cameraOption = {
3335 mirror : false ,
36+ enableOnInactiveState : false ,
3437 targetCanvas : null ,
3538 onSuccess : this . noop ,
3639 onError : this . noop ,
@@ -170,43 +173,57 @@ export default class Camera {
170173 }
171174
172175 private videoRequestAnimationFrame ( ) {
173- const drawImage = ( ) => {
174- if ( ! this . isCameraRunning ) {
175- return ;
176- }
177- if ( this . context ) {
178- this . context . drawImage ( this . video , 0 , 0 , this . video . width , this . video . height ) ;
179- }
180- this . options . onFrame ( this . video ) ;
181- if ( this . visible ) {
182- this . requestAnimationId = requestAnimationFrame ( drawImage ) ;
183- return ;
184- }
185- this . setTimeoutHandler = setTimeout ( ( ) => {
186- drawImage ( ) ;
187- } , 50 ) ;
188- } ;
189- drawImage ( ) ;
176+ if ( this . visible ) {
177+ this . drawImageRAF ( ) ;
178+ return ;
179+ }
180+ this . drawImageST ( ) ;
181+ }
182+
183+ private async drawImageRAF ( ) {
184+ if ( ! this . isCameraRunning ) {
185+ cancelAnimationFrame ( this . requestAnimationId ) ;
186+ this . requestAnimationId = null ;
187+ return ;
188+ }
189+ if ( this . context ) {
190+ this . context . drawImage ( this . video , 0 , 0 , this . video . width , this . video . height ) ;
191+ }
192+ await this . options . onFrame ( this . video ) ;
193+ this . requestAnimationId = requestAnimationFrame ( ( ) => {
194+ this . drawImageRAF ( ) ;
195+ } ) ;
190196 }
191197
198+ private drawImageST ( ) {
199+ if ( ! this . isCameraRunning ) {
200+ clearTimeout ( this . setTimeoutHandler ) ;
201+ this . setTimeoutHandler = null ;
202+ return ;
203+ }
204+ if ( this . context ) {
205+ this . context . drawImage ( this . video , 0 , 0 , this . video . width , this . video . height ) ;
206+ }
207+ this . options . onFrame ( this . video ) ;
208+ this . setTimeoutHandler = setTimeout ( ( ) => {
209+ this . drawImageST ( ) ;
210+ } , 50 ) ;
211+ } ;
212+
192213 public start ( ) {
193214 this . video && this . video . play ( ) ;
194215 if ( this . requestAnimationId || this . setTimeoutHandler ) {
195216 return ;
196217 }
197218 this . isCameraRunning = true ;
219+ this . visible = true ;
198220 this . videoRequestAnimationFrame ( ) ;
199221 }
200222
201223 public pause ( ) {
202224 this . video && this . video . pause ( ) ;
203225 this . isCameraRunning = false ;
204- if ( this . requestAnimationId ) {
205- cancelAnimationFrame ( this . requestAnimationId ) ;
206- clearTimeout ( this . setTimeoutHandler ) ;
207- this . requestAnimationId = null ;
208- this . setTimeoutHandler = null ;
209- }
226+ this . cancelDrawImage ( ) ;
210227 }
211228
212229 public switchCameras ( ) {
@@ -226,20 +243,25 @@ export default class Camera {
226243 this . handleStream ( ) ;
227244 }
228245
246+ private cancelDrawImage ( ) {
247+ clearTimeout ( this . setTimeoutHandler ) ;
248+ this . setTimeoutHandler = null ;
249+ cancelAnimationFrame ( this . requestAnimationId ) ;
250+ this . requestAnimationId = null ;
251+ }
252+
229253 private registerVisiblityEvent ( ) {
230254 document . addEventListener ( 'visibilitychange' , ( ) => {
231255 if ( ! this . isCameraRunning ) {
232256 return ;
233257 }
234- if ( document . visibilityState === 'visible' ) {
235- this . visible = true ;
236- clearTimeout ( this . setTimeoutHandler ) ;
237- this . setTimeoutHandler = null ;
238- }
239- else if ( document . visibilityState === 'hidden' ) {
240- this . visible = false ;
241- this . videoRequestAnimationFrame ( ) ;
258+ this . visible = document . visibilityState === 'visible' ;
259+ this . cancelDrawImage ( ) ;
260+ if ( this . visible ) {
261+ this . drawImageRAF ( ) ;
262+ return ;
242263 }
264+ this . drawImageST ( ) ;
243265 } ) ;
244266 }
245267}
0 commit comments