From f6ab3a9743b3ef9eb28240ef78d96899bc75dc5f Mon Sep 17 00:00:00 2001 From: malangfox Date: Fri, 19 Apr 2024 03:02:17 +0900 Subject: [PATCH] fix: scroll methods end earlier than the given duration --- packages/conveyer/src/Conveyer.ts | 15 +++++--- packages/conveyer/test/unit/Conveyer.spec.ts | 38 +++++++++++++++++++- 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/packages/conveyer/src/Conveyer.ts b/packages/conveyer/src/Conveyer.ts index 87856a8..b065e4d 100644 --- a/packages/conveyer/src/Conveyer.ts +++ b/packages/conveyer/src/Conveyer.ts @@ -293,17 +293,19 @@ class Conveyer extends Component { */ public scrollBy(pos: number, duration = 0) { this._createAnimationParam(); - this._axes!.setBy({ scroll: -pos }, duration); + const nextPos = this._clampScrollPos(this._pos + pos); + this._axes!.setBy({ scroll: this._pos - nextPos }, duration); } /** * Scroll to the given position. * @ko 주어진 위치로 스크롤한다. - * @param - Amount of position to scroll to. 스크롤할 위치의 양. + * @param - Amount of position to scroll to. 스크롤할 위치. * @param - Duration to scroll to that position. 해당 위치로 스크롤하는 시간 */ public scrollTo(pos: number, duration = 0) { this._createAnimationParam(); - this._axes!.setBy({ scroll: this._pos - pos }, duration); + const nextPos = this._clampScrollPos(pos); + this._axes!.setBy({ scroll: this._pos - nextPos }, duration); } /** * Set the items directly to the Conveyer. @@ -554,9 +556,13 @@ class Conveyer extends Component { private _getNativeEvent(e: OnHold | OnChange) { return e?.inputEvent?.srcEvent ? e.inputEvent?.srcEvent : e?.inputEvent; } - private _getNextScrollPos(item: ConveyerItem, options: ScrollIntoViewOptions) { + private _clampScrollPos(pos: number) { const size = this._size; const scrollSize = this._scrollSize; + return Math.max(0, Math.min(pos, scrollSize - size)); + } + private _getNextScrollPos(item: ConveyerItem, options: ScrollIntoViewOptions) { + const size = this._size; const align = options.align || "start"; const padding = options.offset || 0; const itemPos = item!.pos; @@ -570,7 +576,6 @@ class Conveyer extends Component { } else if (align === "center") { scrollPos = itemPos + itemSize / 2 - size / 2 + padding; } - scrollPos = Math.max(0, Math.min(scrollPos, scrollSize - size)); return scrollPos; } private _isMixedWheel(nativeEvent: any) { diff --git a/packages/conveyer/test/unit/Conveyer.spec.ts b/packages/conveyer/test/unit/Conveyer.spec.ts index ffc00f8..2a4481a 100644 --- a/packages/conveyer/test/unit/Conveyer.spec.ts +++ b/packages/conveyer/test/unit/Conveyer.spec.ts @@ -451,6 +451,42 @@ describe("test Conveyer", () => { expect(end.innerHTML).to.be.equals("6"); expect(next.innerHTML).to.be.equals("7"); }); + it("should check whether the scroll animate for given duration even if the target position is outside the scroll area (scrollBy)", async () => { + // Given + conveyer = new Conveyer(".items"); + // 2 3 4 + conveyer.scrollTo(200); + await waitFor(100); + + // When + // to + // 1 2 3 + conveyer.scrollBy(-500, 1000); + await waitFor(300); + + // Then + const items = document.querySelector(".items")!; + expect(items.scrollLeft).to.be.not.equals(0); + expect(conveyer.scrollPos).to.be.not.equals(0); + }); + it("should check whether the scroll animate for given duration even if the target position is outside the scroll area (scrollTo)", async () => { + // Given + conveyer = new Conveyer(".items"); + // 2 3 4 + conveyer.scrollTo(200); + await waitFor(100); + + // When + // to + // 1 2 3 + conveyer.scrollTo(-500, 1000); + await waitFor(300); + + // Then + const items = document.querySelector(".items")!; + expect(items.scrollLeft).to.be.not.equals(0); + expect(conveyer.scrollPos).to.be.not.equals(0); + }); describe("scrollIntoView", () => { it("should check it target moves start when align is start", async () => { // Given @@ -660,7 +696,7 @@ describe("test Conveyer", () => { expect(items.scrollLeft).to.be.equals(400); expect(conveyer.scrollPos).to.be.equals(400); }); - it("should check whether the scroll animate for given duration even if the target position is outside the scroll area", async () => { + it("should check whether the scroll animate for given duration even if the target position is outside the scroll area (scrollIntoView)", async () => { // Given conveyer = new Conveyer(".items"); // 2 3 4