From f7eceda442401d961136f7ca5eb94b5484f47faa Mon Sep 17 00:00:00 2001 From: Tim Kainz Date: Thu, 23 Apr 2026 23:50:27 +0200 Subject: [PATCH] improve hover performance --- src/app/app.css | 1 - .../tech-stack-carousel.css | 30 +------------------ .../tech-stack-carousel.ts | 27 +++++++++++++++-- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/app/app.css b/src/app/app.css index 29f13ae..cd8b240 100644 --- a/src/app/app.css +++ b/src/app/app.css @@ -30,7 +30,6 @@ border: 1px solid #30363d; border-radius: 18px; background: rgba(22, 27, 34, 0.75); - backdrop-filter: blur(9px); z-index: 3; transition: top 260ms ease, diff --git a/src/components/tech-stack-carousel/tech-stack-carousel.css b/src/components/tech-stack-carousel/tech-stack-carousel.css index 0650a39..709d233 100644 --- a/src/components/tech-stack-carousel/tech-stack-carousel.css +++ b/src/components/tech-stack-carousel/tech-stack-carousel.css @@ -37,35 +37,9 @@ h2 { .stack-carousel-column { position: relative; - --left-fade-size: 0px; - --right-fade-size: 0px; width: calc(100% - (var(--carousel-nav-space) * 2)); margin-inline: auto; overflow: hidden; - -webkit-mask-image: linear-gradient( - to right, - transparent 0, - #000 var(--left-fade-size), - #000 calc(100% - var(--right-fade-size)), - transparent 100% - ); - mask-image: linear-gradient( - to right, - transparent 0, - #000 var(--left-fade-size), - #000 calc(100% - var(--right-fade-size)), - transparent 100% - ); - -webkit-mask-repeat: no-repeat; - mask-repeat: no-repeat; -} - -.stack-carousel-column.has-left-fade { - --left-fade-size: var(--carousel-edge-fade-size); -} - -.stack-carousel-column.has-right-fade { - --right-fade-size: var(--carousel-edge-fade-size); } .stack-carousel { @@ -118,8 +92,7 @@ h2 { height: 1.2rem; object-fit: contain; opacity: 0.92; - filter: grayscale(1) brightness(1.25) contrast(0.92); - transition: transform 140ms ease, opacity 140ms ease, filter 140ms ease; + transition: transform 140ms ease, opacity 140ms ease; } .skill-fallback { @@ -159,7 +132,6 @@ h2 { .stack-slide:focus-within .skill-logo { opacity: 1; transform: scale(1.04); - filter: grayscale(1) brightness(1.4) contrast(1); } .carousel-btn { diff --git a/src/components/tech-stack-carousel/tech-stack-carousel.ts b/src/components/tech-stack-carousel/tech-stack-carousel.ts index a569fbb..abe496d 100644 --- a/src/components/tech-stack-carousel/tech-stack-carousel.ts +++ b/src/components/tech-stack-carousel/tech-stack-carousel.ts @@ -30,11 +30,13 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { private isPausePendingStop = false; private isTouchInteracting = false; private isProgrammaticScrollUpdate = false; - private readonly autoScrollSpeedPxPerSecond = 72; + private lastFadeStateUpdateTime = 0; + private readonly autoScrollSpeedPxPerSecond = 48; private readonly speedRampDurationMs = 420; private readonly speedStopThresholdPxPerSecond = 0.5; private readonly touchScrollResumeDelayMs = 1200; private readonly hoverPauseDelayMs = 300; + private readonly fadeUpdateIntervalMs = 96; isAutoScrolling = false; showLeftFade = false; showRightFade = false; @@ -71,6 +73,8 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { this.updateFadeState(); this.resumeAutoScroll(); }, 0); + + document.addEventListener('visibilitychange', this.onVisibilityChange); } ngOnDestroy(): void { @@ -82,6 +86,7 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { this.clearScheduledResume(); this.clearScheduledHoverPause(); this.pauseAutoScroll(); + document.removeEventListener('visibilitychange', this.onVisibilityChange); this.isAutoScrolling = false; } @@ -168,6 +173,10 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { } resumeAutoScroll(): void { + if (document.hidden) { + return; + } + if (this.isTouchInteracting) { this.scheduleResume(this.touchScrollResumeDelayMs); return; @@ -208,7 +217,11 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { this.autoAdvanceStack(carousel, deltaMs, this.currentAutoScrollSpeedPxPerSecond); } - this.updateFadeState(carousel); + if (timestamp - this.lastFadeStateUpdateTime >= this.fadeUpdateIntervalMs) { + this.updateFadeState(carousel); + this.lastFadeStateUpdateTime = timestamp; + } + this.syncAutoScrollState(); if (this.isPausePendingStop && this.currentAutoScrollSpeedPxPerSecond <= this.speedStopThresholdPxPerSecond) { @@ -353,7 +366,17 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy { this.currentAutoScrollSpeedPxPerSecond = 0; this.targetAutoScrollSpeedPxPerSecond = 0; this.lastAutoScrollTime = 0; + this.lastFadeStateUpdateTime = 0; this.syncAutoScrollState(); } + + private readonly onVisibilityChange = (): void => { + if (document.hidden) { + this.pauseAutoScrollImmediately(); + return; + } + + this.scheduleResume(320); + }; }