@@ -139,7 +139,7 @@ class Timer extends Vue {
139139 : Timer .BASE_RADIUS );
140140 private fullCircleLength: number = 2 * Math .PI * this .radius .currentValue ;
141141 private timeoutId: number | null = null ;
142- private updateIntervalId : number | null = null ;
142+ private updateTimeoutId : number | null = null ;
143143 private requestAnimationFrameId: number | null = null ;
144144 private size: number = Timer .BASE_SIZE ;
145145
@@ -151,7 +151,7 @@ class Timer extends Vue {
151151
152152 private destroyed() {
153153 clearTimeout (this .timeoutId );
154- clearInterval (this .updateIntervalId );
154+ clearTimeout (this .updateTimeoutId );
155155 cancelAnimationFrame (this .requestAnimationFrameId );
156156 window .removeEventListener (' resize' , this ._onResize );
157157 }
@@ -209,7 +209,8 @@ class Timer extends Vue {
209209 return { length , lengthWithLineCaps , gap , offset , strokeWidth };
210210 }
211211
212- private get _updateInterval(): number {
212+ private _calculateUpdateInterval(): number {
213+ // Not a getter / computed prop to avoid unnecessary updates when not needed.
213214 const scaleFactor = this .size / Timer .BASE_SIZE ;
214215 const circleLengthPixels = this .fullCircleLength * scaleFactor ;
215216 const steps = circleLengthPixels * 3 ; // update every .33 pixel change for smooth transitions
@@ -226,7 +227,7 @@ class Timer extends Vue {
226227 this .radius .tweenTo (this .detailsShown || this .alwaysShowTime
227228 ? Timer .RADIUS_GROWTH_FACTOR * Timer .BASE_RADIUS
228229 : Timer .BASE_RADIUS , 300 );
229- this ._animateRadius ();
230+ this ._rerender ();
230231 }
231232
232233 @Watch (' startTime' , { immediate: true })
@@ -238,39 +239,26 @@ class Timer extends Vue {
238239 if (this .startTime && this .endTime ) {
239240 this .timeoutId = window .setTimeout (() => this .$emit (Timer .Events .END , this .endTime ),
240241 this .endTime - this .sampledTime );
241- this ._setupUpdateInterval ();
242- }
243- }
244-
245- @Watch (' _updateInterval' )
246- private _setupUpdateInterval() {
247- if (this ._timeLeft === 0 || this .requestAnimationFrameId !== null ) return ;
248-
249- clearInterval (this .updateIntervalId );
250- this .updateIntervalId = window .setInterval (() => {
251- this ._rerender ();
252- if (this ._timeLeft !== 0 ) return ;
253- clearInterval (this .updateIntervalId );
254- }, this ._updateInterval );
255- }
256-
257- private _animateRadius() {
258- if (this .requestAnimationFrameId !== null || this .radius .finished ) return ;
259- clearInterval (this .updateIntervalId ); // stop interval while we render via requestAnimationFrame
260- this .requestAnimationFrameId = requestAnimationFrame (() => {
261242 this ._rerender ();
262- this .requestAnimationFrameId = null ;
263- if (this .radius .finished ) {
264- this ._setupUpdateInterval (); // start update interval again
265- } else {
266- this ._animateRadius ();
267- }
268- });
243+ }
269244 }
270245
271246 private _rerender() {
272247 this .sampledTime = Date .now () + this .timeOffset ;
273248 this .fullCircleLength = 2 * Math .PI * this .radius .currentValue ;
249+
250+ if (this ._timeLeft === 0 && this .radius .finished ) return ;
251+
252+ clearTimeout (this .updateTimeoutId );
253+ cancelAnimationFrame (this .requestAnimationFrameId );
254+
255+ if (! this .radius .finished ) {
256+ // animate radius with high frame rate
257+ this .requestAnimationFrameId = requestAnimationFrame (() => this ._rerender ());
258+ } else {
259+ // update with low frame rate
260+ this .updateTimeoutId = window .setTimeout (() => this ._rerender (), this ._calculateUpdateInterval ());
261+ }
274262 }
275263
276264 private _onResize() {
0 commit comments