diff --git a/src/index.html b/src/index.html index c4abfa2..a770039 100644 --- a/src/index.html +++ b/src/index.html @@ -107,7 +107,16 @@ border-radius: 2px; transition: width 0.3s ease; width: 0%; - margin: 0 0 0.5rem; + margin: 0 0 1rem; + } + + .timeline-labels { + display: flex; + justify-content: space-between; + font-size: 0.7rem; + color: rgba(255,255,255,0.8); + margin-bottom: 0.5rem; + height: 1.2rem; } .control-group { @@ -174,6 +183,7 @@
+
@@ -291,14 +301,14 @@ thumb.classList.toggle('active', index === currentIndex); }); - // Scroll active thumbnail into view - // if (thumbnails[currentIndex]) { - // thumbnails[currentIndex].scrollIntoView({ - // behavior: 'smooth', - // block: 'nearest', - // inline: 'center' - // }); - // } + // Scroll active thumbnail into view + if (thumbnails[currentIndex]) { + thumbnails[currentIndex].scrollIntoView({ + behavior: 'smooth', + block: 'nearest', + inline: 'center' + }); + } } function goToFirst() { @@ -350,6 +360,117 @@ function updateTimeline() { const progress = images.length > 0 ? ((currentIndex + 1) / images.length) * 100 : 0; document.getElementById('timelineProgress').style.width = progress + '%'; + updateTimelineLabels(); + } + + function updateTimelineLabels() { + const labelsContainer = document.getElementById('timelineLabels'); + labelsContainer.innerHTML = ''; + if (images.length === 0) return; + + const firstDate = images[0].createdDate; + const lastDate = images[images.length - 1].createdDate; + const totalDuration = lastDate.getTime() - firstDate.getTime(); + + // Aim for approximately 6-8 labels depending on the container width + const desiredLabels = Math.min(8, Math.max(6, Math.floor(window.innerWidth / 200))); + + const labels = []; + + // Always add the first timestamp + labels.push({ + time: firstDate, + pos: 0 + }); + + // Add evenly spaced timestamps + for (let i = 1; i < desiredLabels - 1; i++) { + const time = new Date(firstDate.getTime() + (totalDuration * i / (desiredLabels - 1))); + + // Find closest image to this time + let closestIdx = 0; + let minDiff = Math.abs(images[0].createdDate - time); + + for (let j = 1; j < images.length; j++) { + const diff = Math.abs(images[j].createdDate - time); + if (diff < minDiff) { + minDiff = diff; + closestIdx = j; + } + } + + const pos = (closestIdx / (images.length - 1)) * 100; + labels.push({ + time: images[closestIdx].createdDate, + pos: pos + }); + } + + // Add the last timestamp + labels.push({ + time: lastDate, + pos: 100 + }); + + // Remove any labels that are too close to each other + const filteredLabels = labels.filter((label, index) => { + if (index === 0) return true; + return Math.abs(label.pos - labels[index - 1].pos) >= 5; + }); + + // Calculate if we need to show seconds (if total duration is less than 5 minutes) + const showSeconds = totalDuration < 5 * 60 * 1000; + + // Calculate optimal spacing between labels + const containerWidth = labelsContainer.offsetWidth; + const labelWidth = 70; // Approximate width of a time label + const minSpacing = labelWidth * 1.5; // Minimum space needed between labels + const maxLabels = Math.floor(containerWidth / minSpacing); + const targetLabels = Math.min(filteredLabels.length, maxLabels); + + // Select evenly spaced labels + const finalLabels = []; + if (filteredLabels.length > 0) { + const step = (filteredLabels.length - 1) / (targetLabels - 1); + for (let i = 0; i < targetLabels; i++) { + const index = Math.round(i * step); + finalLabels.push(filteredLabels[index]); + } + } + + // Round the timestamps + const roundedLabels = finalLabels.map(label => { + const newTime = new Date(label.time); + + if (showSeconds) { + // Round seconds to nearest 5 + const seconds = newTime.getSeconds(); + const roundedSeconds = Math.round(seconds / 5) * 5; + newTime.setSeconds(roundedSeconds); + } else { + // Round minutes to nearest 5 and set seconds to 0 + const minutes = newTime.getMinutes(); + const roundedMinutes = Math.round(minutes / 5) * 5; + newTime.setMinutes(roundedMinutes); + newTime.setSeconds(0); + } + + return { + ...label, + time: newTime + }; + }); + + // Render labels + labelsContainer.style.position = 'relative'; + labelsContainer.innerHTML = roundedLabels.map(l => { + const options = showSeconds + ? {hour: '2-digit', minute:'2-digit', second:'2-digit'} + : {hour: '2-digit', minute:'2-digit'}; + return ` + ${l.time.toLocaleTimeString([], options)} + `; + }).join(''); } function togglePlay() {