Improved player timeline tooltip

This commit is contained in:
WardPearce
2026-02-10 02:26:31 +13:00
parent a6b3ba423b
commit 2d95c5e62b
2 changed files with 61 additions and 33 deletions
+53 -33
View File
@@ -120,6 +120,7 @@
let playerSliderDebounce: ReturnType<typeof setTimeout>;
let playerVolumeElement: HTMLElement | undefined = $state();
let playerIsFullscreen: boolean = $state(false);
let playerTimelineTooltip: HTMLDivElement | undefined = $state();
let playerInitalInteract = true;
const playerTimelineSlider = new Slider({
@@ -1099,26 +1100,41 @@
}
let requestAnimationTooltip: number | undefined;
let latestMouseX: number | undefined;
function timelineMouseMove(event: MouseEvent) {
if (requestAnimationTooltip) return;
latestMouseX = event.clientX;
requestAnimationTooltip = requestAnimationFrame(() => {
if (!playerSliderElement) return;
const rect = playerSliderElement.getBoundingClientRect();
const percent = Math.min(
Math.max((event.clientX - rect.left) / playerSliderElement.clientWidth, 0),
1
);
playerTimelineTimeHover = percent * (data.video.lengthSeconds ?? 0);
document.documentElement.style.setProperty('--timeline-tooltip-left', `${percent * 100}%`);
setPlayerTimelineChapters(playerTimelineTimeHover);
if (!requestAnimationTooltip) {
requestAnimationTooltip = requestAnimationFrame(updateTooltip);
}
}
function updateTooltip() {
if (!playerSliderElement || latestMouseX === undefined) {
requestAnimationTooltip = undefined;
});
return;
}
const rect = playerSliderElement.getBoundingClientRect();
const percent = Math.min(Math.max((latestMouseX - rect.left) / rect.width, 0), 1);
playerTimelineTimeHover = percent * (data.video.lengthSeconds ?? 0);
setPlayerTimelineChapters(playerTimelineTimeHover);
if (playerTimelineTooltip) {
const tooltipWidth = playerTimelineTooltip.offsetWidth;
const tooltipHeight = playerTimelineTooltip.offsetHeight;
const sliderWidth = playerSliderElement.clientWidth;
let left = percent * sliderWidth;
left = Math.min(Math.max(left, tooltipWidth / 2), sliderWidth - tooltipWidth / 2);
playerTimelineTooltip.style.transform = `translateX(${left - tooltipWidth / 2}px)`;
playerTimelineTooltip.style.top = `${-tooltipHeight - 5}px`;
}
requestAnimationTooltip = undefined;
}
function onVideoClick(
@@ -1302,31 +1318,26 @@
onmousemove={timelineMouseMove}
bind:this={playerSliderElement}
>
{#snippet timelineTooltip()}
{#if playerCloestSponsor}
{sponsorSegments[playerCloestSponsor.category]}
<br />
{:else if playerCloestTimestamp}
{playerCloestTimestamp.title}
<br />
{/if}
{/snippet}
<div class="track">
{#if !userManualSeeking}
<div class="tooltip" style="position: absolute;left: var(--timeline-tooltip-left);">
{#if playerCloestSponsor}
{sponsorSegments[playerCloestSponsor.category]}
<br />
{:else if playerCloestTimestamp}
{playerCloestTimestamp.title}
<br />
{/if}
<div bind:this={playerTimelineTooltip} class="timeline tooltip">
{@render timelineTooltip()}
{videoLength(playerTimelineTimeHover)}
</div>
{/if}
<div class="range"></div>
<div {...playerTimelineSlider.thumb}>
<div class="tooltip thumb-tooltip">
{#if playerCloestSponsor}
{sponsorSegments[playerCloestSponsor.category]}
<br />
{:else if playerCloestTimestamp}
{playerCloestTimestamp.title}
<br />
{/if}
{@render timelineTooltip()}
{videoLength(currentTime)}
</div>
</div>
@@ -1808,4 +1819,13 @@
.hide-cursor {
cursor: none;
}
.timeline.tooltip {
position: absolute;
left: 0;
transform: translateX(0%);
transition: none;
pointer-events: none;
will-change: transform;
}
</style>
+8
View File
@@ -121,6 +121,14 @@ menu {
margin: 0 !important;
}
.tooltip {
background-color: var(--surface) !important;
border: 0.1px solid var(--primary) !important;
box-shadow: none !important;
border-radius: 0.25rem !important;
color: var(--on-surface) !important;
}
@media screen and (max-width: 1000px) {
menu.mobile {
position: fixed !important;