Skip to content

Commit acd643e

Browse files
committed
fix: 2D overscroll snapping by clearing expander state and guarding animations
1 parent e7108bf commit acd643e

11 files changed

Lines changed: 110 additions & 3 deletions

@types/scrolltosmooth.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ export declare class ScrollToSmooth {
136136
px: number;
137137
} | false;
138138
protected _getDocumentExpanders(): HTMLDivElement[];
139+
/**
140+
* Clear inline expander dimensions so stale overscroll state never leaks into
141+
* subsequent user-driven or snapped scroll calculations.
142+
*/
143+
protected _clearExpanderSizes(): void;
139144
protected _getScrollEventTarget(): Window | HTMLElement;
140145
protected _getTargetElement(el: Element): Element | null;
141146
private _collectLinks;

dist/plugins/horizontal.cjs.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ const HorizontalScrollPlugin = {
247247
// ----------------------------------------------------------------
248248
proto.scrollTo = function (target, axis) {
249249
this.cancelScroll();
250+
this._isScrolling = true;
250251
const resolvedAxis = axis ?? this.settings.axis ?? 'y';
251252
const container = this.container;
252253
const startX = this._getContainerScrollPosition('x');
@@ -473,6 +474,22 @@ const HorizontalScrollPlugin = {
473474
this.container.style.setProperty('--sts-scroll-x', String(Math.round(currentX)));
474475
this.container.style.setProperty('--sts-scroll-y', String(Math.round(currentY)));
475476
if (elapsed >= duration) {
477+
// Ensure final frame lands exactly on the target and clear any
478+
// transient overscroll expander dimensions from easing overshoot.
479+
if (axis === 'both') {
480+
this._expandDocument(targetX, docWidth, viewWidth, 'x');
481+
this._expandDocument(targetY, docHeight, viewHeight, 'y');
482+
scrollBothAxes(this.container, targetX, targetY);
483+
} else if (axis === 'x') {
484+
this._expandDocument(targetX, docWidth, viewWidth, 'x');
485+
this._setContainerScrollPosition(targetX, 'x');
486+
} else {
487+
this._expandDocument(targetY, docHeight, viewHeight, 'y');
488+
this._setContainerScrollPosition(targetY, 'y');
489+
}
490+
this._clearExpanderSizes();
491+
this.container.style.setProperty('--sts-scroll-x', String(Math.round(targetX)));
492+
this.container.style.setProperty('--sts-scroll-y', String(Math.round(targetY)));
476493
fireOnScrollEnd(this.settings, axis, startX, startY, targetX, targetY);
477494
this._isScrolling = false;
478495
this._processQueue();

dist/plugins/horizontal.iife.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/plugins/horizontal.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ const HorizontalScrollPlugin = {
245245
// ----------------------------------------------------------------
246246
proto.scrollTo = function (target, axis) {
247247
this.cancelScroll();
248+
this._isScrolling = true;
248249
const resolvedAxis = axis ?? this.settings.axis ?? 'y';
249250
const container = this.container;
250251
const startX = this._getContainerScrollPosition('x');
@@ -471,6 +472,22 @@ const HorizontalScrollPlugin = {
471472
this.container.style.setProperty('--sts-scroll-x', String(Math.round(currentX)));
472473
this.container.style.setProperty('--sts-scroll-y', String(Math.round(currentY)));
473474
if (elapsed >= duration) {
475+
// Ensure final frame lands exactly on the target and clear any
476+
// transient overscroll expander dimensions from easing overshoot.
477+
if (axis === 'both') {
478+
this._expandDocument(targetX, docWidth, viewWidth, 'x');
479+
this._expandDocument(targetY, docHeight, viewHeight, 'y');
480+
scrollBothAxes(this.container, targetX, targetY);
481+
} else if (axis === 'x') {
482+
this._expandDocument(targetX, docWidth, viewWidth, 'x');
483+
this._setContainerScrollPosition(targetX, 'x');
484+
} else {
485+
this._expandDocument(targetY, docHeight, viewHeight, 'y');
486+
this._setContainerScrollPosition(targetY, 'y');
487+
}
488+
this._clearExpanderSizes();
489+
this.container.style.setProperty('--sts-scroll-x', String(Math.round(targetX)));
490+
this.container.style.setProperty('--sts-scroll-y', String(Math.round(targetY)));
474491
fireOnScrollEnd(this.settings, axis, startX, startY, targetX, targetY);
475492
this._isScrolling = false;
476493
this._processQueue();

0 commit comments

Comments
 (0)