improve touchscreen scrolling on carousel
All checks were successful
publish.yml / publish (push) Successful in 1m5s
All checks were successful
publish.yml / publish (push) Successful in 1m5s
This commit is contained in:
@@ -10,8 +10,6 @@
|
||||
(mouseleave)="onHoverEnd()"
|
||||
(focusin)="onHoverStart()"
|
||||
(focusout)="onCarouselFocusOut($event)"
|
||||
(touchstart)="onHoverStart()"
|
||||
(touchend)="onHoverEnd()"
|
||||
(click)="onInteractionClick()"
|
||||
>
|
||||
<button class="carousel-btn" type="button" aria-label="Previous technologies" (click)="scrollStack(-1)">
|
||||
@@ -24,6 +22,9 @@
|
||||
[class.is-auto-scrolling]="isAutoScrolling"
|
||||
#stackCarousel
|
||||
(scroll)="onCarouselScroll()"
|
||||
(touchstart)="onTouchStart()"
|
||||
(touchend)="onTouchEnd()"
|
||||
(touchcancel)="onTouchCancel()"
|
||||
role="region"
|
||||
aria-label="Tech stack carousel"
|
||||
>
|
||||
|
||||
@@ -26,9 +26,12 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy {
|
||||
private currentAutoScrollSpeedPxPerSecond = 0;
|
||||
private targetAutoScrollSpeedPxPerSecond = 0;
|
||||
private isPausePendingStop = false;
|
||||
private isTouchInteracting = false;
|
||||
private isProgrammaticScrollUpdate = false;
|
||||
private readonly autoScrollSpeedPxPerSecond = 72;
|
||||
private readonly speedRampDurationMs = 420;
|
||||
private readonly speedStopThresholdPxPerSecond = 0.5;
|
||||
private readonly touchScrollResumeDelayMs = 1200;
|
||||
isAutoScrolling = false;
|
||||
showLeftFade = false;
|
||||
showRightFade = false;
|
||||
@@ -89,9 +92,34 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
onCarouselScroll(): void {
|
||||
if (this.isProgrammaticScrollUpdate) {
|
||||
this.isProgrammaticScrollUpdate = false;
|
||||
this.updateFadeState();
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep autoscroll from fighting touch/momentum scrolling on mobile.
|
||||
this.pauseAutoScrollImmediately();
|
||||
this.scheduleResume(this.touchScrollResumeDelayMs);
|
||||
this.updateFadeState();
|
||||
}
|
||||
|
||||
onTouchStart(): void {
|
||||
this.isTouchInteracting = true;
|
||||
this.clearScheduledResume();
|
||||
this.pauseAutoScrollImmediately();
|
||||
}
|
||||
|
||||
onTouchEnd(): void {
|
||||
this.isTouchInteracting = false;
|
||||
this.scheduleResume(this.touchScrollResumeDelayMs);
|
||||
}
|
||||
|
||||
onTouchCancel(): void {
|
||||
this.isTouchInteracting = false;
|
||||
this.scheduleResume(this.touchScrollResumeDelayMs);
|
||||
}
|
||||
|
||||
onHoverStart(): void {
|
||||
this.pauseAutoScroll();
|
||||
this.clearScheduledResume();
|
||||
@@ -118,6 +146,11 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
resumeAutoScroll(): void {
|
||||
if (this.isTouchInteracting) {
|
||||
this.scheduleResume(this.touchScrollResumeDelayMs);
|
||||
return;
|
||||
}
|
||||
|
||||
this.isPausePendingStop = false;
|
||||
this.targetAutoScrollSpeedPxPerSecond = this.autoScrollSpeedPxPerSecond;
|
||||
this.syncAutoScrollState();
|
||||
@@ -242,6 +275,7 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy {
|
||||
// Normalize only when moving past the duplicated track boundary to avoid abrupt remaps on quick re-entry.
|
||||
this.virtualScrollLeft = nextVirtualScrollLeft >= loopWidth ? nextVirtualScrollLeft - loopWidth : nextVirtualScrollLeft;
|
||||
|
||||
this.isProgrammaticScrollUpdate = true;
|
||||
carousel.scrollLeft = this.virtualScrollLeft;
|
||||
}
|
||||
|
||||
@@ -277,5 +311,20 @@ export class TechStackCarousel implements AfterViewInit, OnDestroy {
|
||||
this.targetAutoScrollSpeedPxPerSecond > this.speedStopThresholdPxPerSecond ||
|
||||
this.currentAutoScrollSpeedPxPerSecond > this.speedStopThresholdPxPerSecond;
|
||||
}
|
||||
|
||||
private pauseAutoScrollImmediately(): void {
|
||||
this.clearScheduledResume();
|
||||
|
||||
if (this.autoScrollFrameId !== null) {
|
||||
cancelAnimationFrame(this.autoScrollFrameId);
|
||||
this.autoScrollFrameId = null;
|
||||
}
|
||||
|
||||
this.isPausePendingStop = false;
|
||||
this.currentAutoScrollSpeedPxPerSecond = 0;
|
||||
this.targetAutoScrollSpeedPxPerSecond = 0;
|
||||
this.lastAutoScrollTime = 0;
|
||||
this.syncAutoScrollState();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user