web-map/src/hooks/useTimelineTicks.ts

57 lines
1.6 KiB
TypeScript
Raw Normal View History

import { computed, type Ref } from 'vue';
export interface Tick {
position: string; // Percentage position within the view
label: string | null;
isMajor: boolean;
}
// Formats time as hh:mm for labels
const formatLabelTime = (ms: number): string => {
const totalSeconds = Math.floor(ms / 1000);
const hours = Math.floor(totalSeconds / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const pad = (num: number) => num.toString().padStart(2, '0');
return `${pad(hours)}:${pad(minutes)}`;
};
export function useTimelineTicks(viewStartTime: Ref<number>, viewEndTime: Ref<number>) {
const ticks = computed<Tick[]>(() => {
const startTime = viewStartTime.value;
const endTime = viewEndTime.value;
const viewDuration = endTime - startTime;
if (isNaN(startTime) || isNaN(endTime) || viewDuration <= 0) {
return [];
}
const result: Tick[] = [];
// For a 1-hour view, we use fixed intervals
const majorTickInterval = 10 * 60 * 1000; // Every 10 minutes for labels
const minorTickInterval = 1 * 60 * 1000; // Every 1 minute for small ticks
for (let time = startTime; time <= endTime; time += minorTickInterval) {
// Ensure we only create ticks at exact minute marks relative to the start of the day
if (time % minorTickInterval !== 0) {
continue;
}
const relativeTime = time - startTime;
const isMajor = time % majorTickInterval === 0;
result.push({
position: `${(relativeTime / viewDuration) * 100}%`,
label: isMajor ? formatLabelTime(time) : null,
isMajor,
});
}
return result;
});
return {
ticks,
};
}