123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- <script setup>
- const props = defineProps({
- step_count: {
- type: Number,
- default: 10
- },
- period : Number,
- generated_at: Number,
- autostart: {
- type: Boolean,
- default: true
- },
- })
- const generatedAt = ref(null)
- const remainingTimeout = ref(null)
- const initialStepToNextStepTimeout = ref(null)
- const stepToStepInterval = ref(null)
- const stepIndex = ref(null)
- // |<----period p----->|
- // | | |
- // |------- ··· ------------|--------|----------|---------->
- // | | | |
- // unix T0 Tp.start Tgen_at Tp.end
- // | | |
- // elapsedTimeInCurrentPeriod--|<------>| |
- // (in ms) | | |
- // ● ● ● ● ●|● ◌ ◌ ◌ ◌ |
- // | | || |
- // | | |<-------->|--remainingTimeBeforeEndOfPeriod (for remainingTimeout)
- // durationBetweenTwoSteps-->|-|< ||
- // (for stepToStepInterval) | | >||<---durationFromInitialToNextStep (for initialStepToNextStepTimeout)
- // |
- // |
- // stepIndex
- const elapsedTimeInCurrentPeriod = computed(() => {
- return generatedAt.value % props.period
- })
- const remainingTimeBeforeEndOfPeriod = computed(() => {
- return props.period - elapsedTimeInCurrentPeriod.value
- })
- const durationBetweenTwoSteps = computed(() => {
- return props.period / props.step_count
- })
- const initialStepIndex = computed(() => {
- let relativePosition = (elapsedTimeInCurrentPeriod.value * props.step_count) / props.period
- return (Math.floor(relativePosition) + 0)
- })
- const emit = defineEmits(['loop-started', 'loop-ended', 'stepped-up'])
- /**
- * Starts looping
- */
- const startLoop = (generated_at = null) => {
- clearLooper()
- generatedAt.value = generated_at != null ? generated_at : props.generated_at
- emit('loop-started', initialStepIndex.value)
- stepIndex.value = initialStepIndex.value
- // Main timeout that runs until the end of the period
- remainingTimeout.value = setTimeout(function() {
- clearLooper()
- emit('loop-ended')
- }, remainingTimeBeforeEndOfPeriod.value * 1000);
- // During the remainingTimeout countdown we emit an event every durationBetweenTwoSteps seconds,
- // except for the first next dot
- let durationFromInitialToNextStep = (Math.ceil(elapsedTimeInCurrentPeriod.value / durationBetweenTwoSteps.value) * durationBetweenTwoSteps.value) - elapsedTimeInCurrentPeriod.value
- initialStepToNextStepTimeout.value = setTimeout(function() {
- if( durationFromInitialToNextStep > 0 ) {
- stepIndex.value += 1
- emit('stepped-up', stepIndex.value)
- }
- stepToStepInterval.value = setInterval(function() {
- stepIndex.value += 1
- emit('stepped-up', stepIndex.value)
- }, durationBetweenTwoSteps.value * 1000)
- }, durationFromInitialToNextStep * 1000)
- }
- /**
- * Resets all timers and internal vars
- */
- const clearLooper = () => {
- clearTimeout(remainingTimeout.value)
- clearTimeout(initialStepToNextStepTimeout.value)
- clearInterval(stepToStepInterval.value)
- stepIndex.value = generatedAt.value = null
- }
- onMounted(() => {
- if (props.autostart == true) {
- startLoop()
- }
- })
- onUnmounted(() => {
- clearLooper()
- })
- defineExpose({
- startLoop,
- clearLooper,
- props
- })
- </script>
- <template>
- <div>
- </div>
- </template>
|