refactor(chronometer): improved chronometer precision
This commit is contained in:
		
							parent
							
								
									fda0b0ca25
								
							
						
					
					
						commit
						e48d60b1ed
					
				| @ -1,12 +1,13 @@ | ||||
| import { describe, expect, it } from 'vitest'; | ||||
| import { formatChronometerTime } from './chronometer.service'; | ||||
| import { formatMs } from './chronometer.service'; | ||||
| 
 | ||||
| describe('chronometer', () => { | ||||
|   describe('formatChronometerTime', () => { | ||||
|     it('format the elapsed time', () => { | ||||
|       expect(formatChronometerTime({ elapsed: 123456 })).toEqual('02:03.456'); | ||||
|       expect(formatChronometerTime({ elapsed: 123456, msPerUnit: 100 })).toEqual('03:25:45.600'); | ||||
|       expect(formatChronometerTime({ elapsed: 12345600 })).toEqual('03:25:45.600'); | ||||
|       expect(formatMs(0)).toEqual('00:00.000'); | ||||
|       expect(formatMs(1)).toEqual('00:00.001'); | ||||
|       expect(formatMs(123456)).toEqual('02:03.456'); | ||||
|       expect(formatMs(12345600)).toEqual('03:25:45.600'); | ||||
|     }); | ||||
|   }); | ||||
| }); | ||||
|  | ||||
| @ -1,10 +1,8 @@ | ||||
| export function formatChronometerTime({ elapsed, msPerUnit = 1 }: { elapsed: number; msPerUnit?: number }) { | ||||
|   const elapsedMs = elapsed * msPerUnit; | ||||
| 
 | ||||
|   const ms = elapsedMs % 1000; | ||||
|   const secs = ((elapsedMs - ms) / 1000) % 60; | ||||
|   const mins = (((elapsedMs - ms) / 1000 - secs) / 60) % 60; | ||||
|   const hrs = (((elapsedMs - ms) / 1000 - secs) / 60 - mins) / 60; | ||||
| export function formatMs(msTotal: number) { | ||||
|   const ms = msTotal % 1000; | ||||
|   const secs = ((msTotal - ms) / 1000) % 60; | ||||
|   const mins = (((msTotal - ms) / 1000 - secs) / 60) % 60; | ||||
|   const hrs = (((msTotal - ms) / 1000 - secs) / 60 - mins) / 60; | ||||
|   const hrsString = hrs > 0 ? `${hrs.toString().padStart(2, '0')}:` : ''; | ||||
| 
 | ||||
|   return `${hrsString}${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}.${ms | ||||
|  | ||||
| @ -1,11 +1,11 @@ | ||||
| <template> | ||||
|   <div> | ||||
|     <n-card> | ||||
|       <div class="duration">{{ formatChronometerTime({ elapsed: counter, msPerUnit }) }}</div> | ||||
|       <div class="duration">{{ formatMs(counter) }}</div> | ||||
|     </n-card> | ||||
|     <br /> | ||||
|     <n-space justify="center"> | ||||
|       <n-button v-if="!isActive" secondary type="primary" @click="resume">Start</n-button> | ||||
|       <n-button v-if="!isRunning" secondary type="primary" @click="resume">Start</n-button> | ||||
|       <n-button v-else secondary type="warning" @click="pause">Stop</n-button> | ||||
| 
 | ||||
|       <n-button secondary @click="counter = 0">Reset</n-button> | ||||
| @ -14,12 +14,33 @@ | ||||
| </template> | ||||
| 
 | ||||
| <script setup lang="ts"> | ||||
| import { useInterval } from '@vueuse/core'; | ||||
| import { formatChronometerTime } from './chronometer.service'; | ||||
| import { useRafFn } from '@vueuse/core'; | ||||
| import { ref } from 'vue'; | ||||
| import { formatMs } from './chronometer.service'; | ||||
| 
 | ||||
| const msPerUnit = 10; | ||||
| const isRunning = ref(false); | ||||
| const counter = ref(0); | ||||
| 
 | ||||
| const { counter, pause, resume, isActive } = useInterval(msPerUnit, { controls: true, immediate: false }); | ||||
| let previousRafDate = Date.now(); | ||||
| const { pause: pauseRaf, resume: resumeRaf } = useRafFn( | ||||
|   () => { | ||||
|     const deltaMs = Date.now() - previousRafDate; | ||||
|     previousRafDate = Date.now(); | ||||
|     counter.value += deltaMs; | ||||
|   }, | ||||
|   { immediate: false }, | ||||
| ); | ||||
| 
 | ||||
| function resume() { | ||||
|   previousRafDate = Date.now(); | ||||
|   resumeRaf(); | ||||
|   isRunning.value = true; | ||||
| } | ||||
| 
 | ||||
| function pause() { | ||||
|   pauseRaf(); | ||||
|   isRunning.value = false; | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="less" scoped> | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user