@@ -253,42 +253,64 @@ const photoBooth = (function () {
253253 const stop =
254254 parseInt ( config . preview . stop_time , 10 ) > seconds ? 0 : parseInt ( config . preview . stop_time , 10 ) ;
255255 photoboothTools . console . logDev ( 'Preview: core: stop at ' + stop ) ;
256- const interval = setInterval ( ( ) => {
257- photoboothTools . console . logDev ( 'Preview: core: countdown seconds ' + seconds ) ;
258- api . countdown . element . innerHTML = '' ;
259- if ( seconds > 0 ) {
260- // dont show the 0 as countdown number
261- const numberElement = document . createElement ( 'div' ) ;
262- numberElement . classList . add ( 'countdown-number' ) ;
263- numberElement . textContent = Number ( seconds ) . toString ( ) ;
264- api . countdown . element . appendChild ( numberElement ) ;
265- }
266- if ( config . sound . enabled && config . sound . countdown_enabled ) {
267- const soundfile = photoboothTools . getSound ( 'counter-' + Number ( seconds ) . toString ( ) ) ;
268- if ( soundfile !== null ) {
269- api . countdown . audioElement . src = soundfile ;
270- api . countdown . audioElement . play ( ) . catch ( ( error ) => {
271- photoboothTools . console . log ( 'Error with audio.play: ' + error ) ;
272- } ) ;
256+ const startTime = performance . now ( ) ;
257+ const targetTime = startTime + seconds * 1000 ;
258+ let lastSecondShown = null ;
259+
260+ const tick = ( ) => {
261+ const now = performance . now ( ) ;
262+ const remainingSeconds = Math . ceil ( ( targetTime - now ) / 1000 ) ;
263+
264+ // Only update when we moved to the next integer second
265+ if ( remainingSeconds !== lastSecondShown ) {
266+ lastSecondShown = remainingSeconds ;
267+ photoboothTools . console . logDev ( 'Preview: core: countdown seconds ' + remainingSeconds ) ;
268+ api . countdown . element . innerHTML = '' ;
269+ if ( remainingSeconds > 0 ) {
270+ // dont show the 0 as countdown number
271+ const numberElement = document . createElement ( 'div' ) ;
272+ numberElement . classList . add ( 'countdown-number' ) ;
273+ numberElement . textContent = Number ( remainingSeconds ) . toString ( ) ;
274+ api . countdown . element . appendChild ( numberElement ) ;
273275 }
274- }
276+ if ( config . sound . enabled && config . sound . countdown_enabled ) {
277+ const soundfile = photoboothTools . getSound (
278+ 'counter-' + Number ( remainingSeconds ) . toString ( )
279+ ) ;
280+ if ( soundfile !== null ) {
281+ api . countdown . audioElement . src = soundfile ;
282+ api . countdown . audioElement . play ( ) . catch ( ( error ) => {
283+ photoboothTools . console . log ( 'Error with audio.play: ' + error ) ;
284+ } ) ;
285+ }
286+ }
287+
288+ // stop second hit
289+ if ( remainingSeconds === stop && ! config . preview . camTakesPic ) {
290+ photoboothTools . console . logDev ( 'Preview: core: stopping preview at countdown.' ) ;
291+ photoboothPreview . stopPreview ( ) ;
292+ }
293+
294+ // after 1 is faded out, on second 0
295+ if ( remainingSeconds <= 0 ) {
296+ photoboothTools . console . log ( 'Countdown finished.' ) ;
297+ api . countdown . destroy ( ) ;
298+ resolve ( ) ;
275299
276- // stop second hit
277- if ( seconds === stop && ! config . preview . camTakesPic ) {
278- photoboothTools . console . logDev ( 'Preview: core: stopping preview at countdown.' ) ;
279- photoboothPreview . stopPreview ( ) ;
300+ return ;
301+ }
280302 }
281303
282- // after 1 is faded out, on second 0
283- if ( seconds <= 0 ) {
284- photoboothTools . console . log ( 'Countdown finished.' ) ;
285- clearInterval ( interval ) ;
286- api . countdown . destroy ( ) ;
287- resolve ( ) ;
304+ if ( remainingSeconds > 0 ) {
305+ if ( typeof window . requestAnimationFrame === 'function' ) {
306+ window . requestAnimationFrame ( tick ) ;
307+ } else {
308+ setTimeout ( tick , 50 ) ;
309+ }
288310 }
311+ } ;
289312
290- seconds -- ;
291- } , 1000 ) ;
313+ tick ( ) ;
292314 } ) ;
293315 }
294316 } ;
0 commit comments