From 66bcb7ef1f85d58153fd989dd723ed3d29b5d897 Mon Sep 17 00:00:00 2001 From: malangfox Date: Thu, 27 Jun 2024 13:18:41 +0900 Subject: [PATCH 1/2] feat: add interruptable option to Arrow plugin --- .gitignore | 1 + package-lock.json | 193 +++++++++++++++++-------------------- package.json | 4 +- src/Arrow.ts | 50 +++++++--- test/manual/arrow.html | 70 +++++++------- test/manual/css/common.css | 4 + test/unit/Arrow.spec.ts | 68 ++++++++++++- 7 files changed, 232 insertions(+), 158 deletions(-) diff --git a/.gitignore b/.gitignore index 1cf43a3..20b1ff8 100644 --- a/.gitignore +++ b/.gitignore @@ -209,3 +209,4 @@ demo/_data/version.yml outjs/ declaration/ +dist/ diff --git a/package-lock.json b/package-lock.json index 8356339..b22f04f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "@egjs/flicking-plugins", - "version": "4.3.0", + "version": "4.7.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@egjs/flicking-plugins", - "version": "4.3.0", + "version": "4.7.1", "license": "MIT", "devDependencies": { "@egjs/build-helper": "0.0.5", - "@egjs/flicking": "^4.4.2", + "@egjs/flicking": "^4.11.3", "@egjs/release-helper": "0.0.3", "@types/chai": "^4.0.10", "@types/karma-chai": "^0.1.1", @@ -52,7 +52,7 @@ "typescript": "^4.2.3" }, "peerDependencies": { - "@egjs/flicking": "^4.1.0" + "@egjs/flicking": "^4.11.3" } }, "node_modules/@babel/code-frame": { @@ -180,29 +180,32 @@ "to-fast-properties": "^2.0.0" } }, + "node_modules/@cfcs/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@cfcs/core/-/core-0.1.0.tgz", + "integrity": "sha512-kvYX0RpL45XTHJ5sW7teNbKeAa7pK3nNqaJPoFfZDPTIBJOkTtRD3QhkBG+O3Hu69a8xeMoPvF6y/RtJ6JUOdA==", + "dev": true, + "dependencies": { + "@egjs/component": "^3.0.4" + } + }, "node_modules/@egjs/agent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.3.0.tgz", - "integrity": "sha512-ENhwkOW6rnYW8IuXJwvECIAzj7nMxq+ctB8uCJ+mKnoKK8tGiv3YXtN6nuaOov2YmXdRdwafSz9rhgRNXswX/A==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.4.3.tgz", + "integrity": "sha512-XvksSENe8wPeFlEVouvrOhKdx8HMniJ3by7sro2uPF3M6QqWwjzVcmvwoPtdjiX8O1lfRoLhQMp1a7NGlVTdIA==", "dev": true }, "node_modules/@egjs/axes": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@egjs/axes/-/axes-2.8.0.tgz", - "integrity": "sha512-WPMIM/ExZBS8guD3oeNr6YGDn2xSnj0YUZHWvY/NWvTQIs7A2O7WxJivYgzcg7r2q0RYtzrdpHn+982iaKCLSw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@egjs/axes/-/axes-3.9.0.tgz", + "integrity": "sha512-V+HxHxEGmlu/0yJ9kqlj2doiJt1yVeROTy/0Qf+IaJ9hMabjzUgfYffGR+3atcRpejjGbcpAIiBrGbAkDVaLjg==", "dev": true, "dependencies": { + "@cfcs/core": "^0.1.0", "@egjs/agent": "^2.2.1", - "@egjs/component": "^2.2.2", - "@egjs/hammerjs": "^2.0.15" + "@egjs/component": "^3.0.1" } }, - "node_modules/@egjs/axes/node_modules/@egjs/component": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-2.2.2.tgz", - "integrity": "sha512-2m6nu6/Mbs6VnoT4IHFGUBX6V82Zp01zDmlWpIJ3fMatHpe7BB1qUYFgMmSWGY0uOvOl4plvflwbCRUAGMfwWQ==", - "dev": true - }, "node_modules/@egjs/build-helper": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/@egjs/build-helper/-/build-helper-0.0.5.tgz", @@ -220,54 +223,46 @@ } }, "node_modules/@egjs/component": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-3.0.1.tgz", - "integrity": "sha512-Hus9GMXOVfHBzyumyeRL1TkN60LhGen+e9FpqXqbS9jA9hDYEE1AH3ulahbBGhRdMs4uXYl3hRnB5kGZRb9n7Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@egjs/component/-/component-3.0.5.tgz", + "integrity": "sha512-cLcGizTrrUNA2EYE3MBmEDt2tQv1joVP1Q3oDisZ5nw0MZDx2kcgEXM+/kZpfa/PAkFvYVhRUZwytIQWoN3V/w==", "dev": true }, "node_modules/@egjs/flicking": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@egjs/flicking/-/flicking-4.4.2.tgz", - "integrity": "sha512-ZzoXkXH1OJc78gb2LGewHDLJO6RcGVKgpf5fTUhyyjne8eG04poZrhkvCSKdbln4CO3oD899WrR+hRj92PJawg==", + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@egjs/flicking/-/flicking-4.11.3.tgz", + "integrity": "sha512-90IbXMwdiNL4+Yrvfgi4zYk9XKLbjVaVLus5lIl28twQiT/KV3W9ypJOJEK7U5U9oS2q7dn8OJZolD8JNOsxag==", "dev": true, "dependencies": { - "@egjs/axes": "^2.8.0", + "@egjs/axes": "^3.9.0", "@egjs/component": "^3.0.1", - "@egjs/imready": "^1.1.3", - "@egjs/list-differ": "^1.0.0" + "@egjs/imready": "^1.3.1", + "@egjs/list-differ": "^1.0.1" } }, - "node_modules/@egjs/hammerjs": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", - "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", + "node_modules/@egjs/imready": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@egjs/imready/-/imready-1.4.1.tgz", + "integrity": "sha512-JIOBs4lB7FYdsKi5uvz2j3SObX8eShtZjtqlOH41tm185aJOQZwiKBK8+V4MxzG4X6DqVhpdN8UcuVwBbElfsg==", "dev": true, "dependencies": { - "@types/hammerjs": "^2.0.36" - }, - "engines": { - "node": ">=0.8.0" + "@cfcs/core": "^0.0.24", + "@egjs/component": "^3.0.1" } }, - "node_modules/@egjs/imready": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@egjs/imready/-/imready-1.1.4.tgz", - "integrity": "sha512-LyAyriK4syI3URtZtTHE68sfQRBJAcdhzJL1m2N+6QHGwo+M0YNC1HwcLx/ze15MDfv+gGXfQrlF6jPHzK+V4A==", + "node_modules/@egjs/imready/node_modules/@cfcs/core": { + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/@cfcs/core/-/core-0.0.24.tgz", + "integrity": "sha512-feB38qu+eDk0Pggh/yR7gjaNmvUYA2uCxHP3Pz2MLE4LZ/9jPdtu8bzCSI47yTEhWyZCF5Pk698hdz8IN2mTjA==", "dev": true, "dependencies": { - "@egjs/component": "^2.2.2" + "@egjs/component": "^3.0.4" } }, - "node_modules/@egjs/imready/node_modules/@egjs/component": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-2.2.2.tgz", - "integrity": "sha512-2m6nu6/Mbs6VnoT4IHFGUBX6V82Zp01zDmlWpIJ3fMatHpe7BB1qUYFgMmSWGY0uOvOl4plvflwbCRUAGMfwWQ==", - "dev": true - }, "node_modules/@egjs/list-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@egjs/list-differ/-/list-differ-1.0.0.tgz", - "integrity": "sha512-HsbMKc0ZAQH+EUeCmI/2PvTYSybmkaWwakU8QGDYYgMVIg9BQ5sM0A0Nnombjxo2+JzXHxmH+jw//yGX+y6GYw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@egjs/list-differ/-/list-differ-1.0.1.tgz", + "integrity": "sha512-OTFTDQcWS+1ZREOdCWuk5hCBgYO4OsD30lXcOCyVOAjXMhgL5rBRDnt/otb6Nz8CzU0L/igdcaQBDLWc4t9gvg==", "dev": true }, "node_modules/@egjs/release-helper": { @@ -442,12 +437,6 @@ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "dev": true }, - "node_modules/@types/hammerjs": { - "version": "2.0.39", - "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.39.tgz", - "integrity": "sha512-lYR2Y/tV2ujpk/WyUc7S0VLI0a9hrtVIN9EwnrNo5oSEJI2cK2/XrgwOQmXLL3eTulOESvh9qP6si9+DWM9cOA==", - "dev": true - }, "node_modules/@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", @@ -11647,29 +11636,30 @@ "to-fast-properties": "^2.0.0" } }, + "@cfcs/core": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@cfcs/core/-/core-0.1.0.tgz", + "integrity": "sha512-kvYX0RpL45XTHJ5sW7teNbKeAa7pK3nNqaJPoFfZDPTIBJOkTtRD3QhkBG+O3Hu69a8xeMoPvF6y/RtJ6JUOdA==", + "dev": true, + "requires": { + "@egjs/component": "^3.0.4" + } + }, "@egjs/agent": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.3.0.tgz", - "integrity": "sha512-ENhwkOW6rnYW8IuXJwvECIAzj7nMxq+ctB8uCJ+mKnoKK8tGiv3YXtN6nuaOov2YmXdRdwafSz9rhgRNXswX/A==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/@egjs/agent/-/agent-2.4.3.tgz", + "integrity": "sha512-XvksSENe8wPeFlEVouvrOhKdx8HMniJ3by7sro2uPF3M6QqWwjzVcmvwoPtdjiX8O1lfRoLhQMp1a7NGlVTdIA==", "dev": true }, "@egjs/axes": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/@egjs/axes/-/axes-2.8.0.tgz", - "integrity": "sha512-WPMIM/ExZBS8guD3oeNr6YGDn2xSnj0YUZHWvY/NWvTQIs7A2O7WxJivYgzcg7r2q0RYtzrdpHn+982iaKCLSw==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@egjs/axes/-/axes-3.9.0.tgz", + "integrity": "sha512-V+HxHxEGmlu/0yJ9kqlj2doiJt1yVeROTy/0Qf+IaJ9hMabjzUgfYffGR+3atcRpejjGbcpAIiBrGbAkDVaLjg==", "dev": true, "requires": { + "@cfcs/core": "^0.1.0", "@egjs/agent": "^2.2.1", - "@egjs/component": "^2.2.2", - "@egjs/hammerjs": "^2.0.15" - }, - "dependencies": { - "@egjs/component": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-2.2.2.tgz", - "integrity": "sha512-2m6nu6/Mbs6VnoT4IHFGUBX6V82Zp01zDmlWpIJ3fMatHpe7BB1qUYFgMmSWGY0uOvOl4plvflwbCRUAGMfwWQ==", - "dev": true - } + "@egjs/component": "^3.0.1" } }, "@egjs/build-helper": { @@ -11689,53 +11679,48 @@ } }, "@egjs/component": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-3.0.1.tgz", - "integrity": "sha512-Hus9GMXOVfHBzyumyeRL1TkN60LhGen+e9FpqXqbS9jA9hDYEE1AH3ulahbBGhRdMs4uXYl3hRnB5kGZRb9n7Q==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@egjs/component/-/component-3.0.5.tgz", + "integrity": "sha512-cLcGizTrrUNA2EYE3MBmEDt2tQv1joVP1Q3oDisZ5nw0MZDx2kcgEXM+/kZpfa/PAkFvYVhRUZwytIQWoN3V/w==", "dev": true }, "@egjs/flicking": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@egjs/flicking/-/flicking-4.4.2.tgz", - "integrity": "sha512-ZzoXkXH1OJc78gb2LGewHDLJO6RcGVKgpf5fTUhyyjne8eG04poZrhkvCSKdbln4CO3oD899WrR+hRj92PJawg==", + "version": "4.11.3", + "resolved": "https://registry.npmjs.org/@egjs/flicking/-/flicking-4.11.3.tgz", + "integrity": "sha512-90IbXMwdiNL4+Yrvfgi4zYk9XKLbjVaVLus5lIl28twQiT/KV3W9ypJOJEK7U5U9oS2q7dn8OJZolD8JNOsxag==", "dev": true, "requires": { - "@egjs/axes": "^2.8.0", + "@egjs/axes": "^3.9.0", "@egjs/component": "^3.0.1", - "@egjs/imready": "^1.1.3", - "@egjs/list-differ": "^1.0.0" - } - }, - "@egjs/hammerjs": { - "version": "2.0.17", - "resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz", - "integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==", - "dev": true, - "requires": { - "@types/hammerjs": "^2.0.36" + "@egjs/imready": "^1.3.1", + "@egjs/list-differ": "^1.0.1" } }, "@egjs/imready": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@egjs/imready/-/imready-1.1.4.tgz", - "integrity": "sha512-LyAyriK4syI3URtZtTHE68sfQRBJAcdhzJL1m2N+6QHGwo+M0YNC1HwcLx/ze15MDfv+gGXfQrlF6jPHzK+V4A==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@egjs/imready/-/imready-1.4.1.tgz", + "integrity": "sha512-JIOBs4lB7FYdsKi5uvz2j3SObX8eShtZjtqlOH41tm185aJOQZwiKBK8+V4MxzG4X6DqVhpdN8UcuVwBbElfsg==", "dev": true, "requires": { - "@egjs/component": "^2.2.2" + "@cfcs/core": "^0.0.24", + "@egjs/component": "^3.0.1" }, "dependencies": { - "@egjs/component": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/@egjs/component/-/component-2.2.2.tgz", - "integrity": "sha512-2m6nu6/Mbs6VnoT4IHFGUBX6V82Zp01zDmlWpIJ3fMatHpe7BB1qUYFgMmSWGY0uOvOl4plvflwbCRUAGMfwWQ==", - "dev": true + "@cfcs/core": { + "version": "0.0.24", + "resolved": "https://registry.npmjs.org/@cfcs/core/-/core-0.0.24.tgz", + "integrity": "sha512-feB38qu+eDk0Pggh/yR7gjaNmvUYA2uCxHP3Pz2MLE4LZ/9jPdtu8bzCSI47yTEhWyZCF5Pk698hdz8IN2mTjA==", + "dev": true, + "requires": { + "@egjs/component": "^3.0.4" + } } } }, "@egjs/list-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@egjs/list-differ/-/list-differ-1.0.0.tgz", - "integrity": "sha512-HsbMKc0ZAQH+EUeCmI/2PvTYSybmkaWwakU8QGDYYgMVIg9BQ5sM0A0Nnombjxo2+JzXHxmH+jw//yGX+y6GYw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@egjs/list-differ/-/list-differ-1.0.1.tgz", + "integrity": "sha512-OTFTDQcWS+1ZREOdCWuk5hCBgYO4OsD30lXcOCyVOAjXMhgL5rBRDnt/otb6Nz8CzU0L/igdcaQBDLWc4t9gvg==", "dev": true }, "@egjs/release-helper": { @@ -11881,12 +11866,6 @@ "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", "dev": true }, - "@types/hammerjs": { - "version": "2.0.39", - "resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.39.tgz", - "integrity": "sha512-lYR2Y/tV2ujpk/WyUc7S0VLI0a9hrtVIN9EwnrNo5oSEJI2cK2/XrgwOQmXLL3eTulOESvh9qP6si9+DWM9cOA==", - "dev": true - }, "@types/json-schema": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", diff --git a/package.json b/package.json index c8e806f..58f3075 100644 --- a/package.json +++ b/package.json @@ -58,11 +58,11 @@ "not op_mini all" ], "peerDependencies": { - "@egjs/flicking": "^4.1.0" + "@egjs/flicking": "^4.11.3" }, "devDependencies": { "@egjs/build-helper": "0.0.5", - "@egjs/flicking": "^4.4.2", + "@egjs/flicking": "^4.11.3", "@egjs/release-helper": "0.0.3", "@types/chai": "^4.0.10", "@types/karma-chai": "^0.1.1", diff --git a/src/Arrow.ts b/src/Arrow.ts index 699de03..c5f2572 100644 --- a/src/Arrow.ts +++ b/src/Arrow.ts @@ -1,4 +1,4 @@ -import Flicking, { EVENTS, FlickingError, Plugin } from "@egjs/flicking"; +import Flicking, { EVENTS, FlickingError, Plugin, WillChangeEvent } from "@egjs/flicking"; import { BROWSER } from "./event"; import { ARROW } from "./const"; @@ -11,6 +11,7 @@ interface ArrowOptions { disabledClass: string; moveCount: number; moveByViewportSize: boolean; + interruptable: boolean; } /** @@ -23,6 +24,7 @@ class Arrow implements Plugin { private _flicking: Flicking | null = null; private _prevEl: HTMLElement; private _nextEl: HTMLElement; + private _nextIndex: number; /* Options */ private _parentEl: ArrowOptions["parentEl"]; @@ -31,6 +33,7 @@ class Arrow implements Plugin { private _disabledClass: ArrowOptions["disabledClass"]; private _moveCount: ArrowOptions["moveCount"]; private _moveByViewportSize: ArrowOptions["moveByViewportSize"]; + private _interruptable: ArrowOptions["interruptable"]; public get prevEl() { return this._prevEl; } public get nextEl() { return this._nextEl; } @@ -41,6 +44,7 @@ class Arrow implements Plugin { public get disabledClass() { return this._disabledClass; } public get moveCount() { return this._moveCount; } public get moveByViewportSize() { return this._moveByViewportSize; } + public get interruptable() { return this._interruptable; } public set parentEl(val: ArrowOptions["parentEl"]) { this._parentEl = val; } public set prevElSelector(val: ArrowOptions["prevElSelector"]) { this._prevElSelector = val; } @@ -48,6 +52,7 @@ class Arrow implements Plugin { public set disabledClass(val: ArrowOptions["disabledClass"]) { this._disabledClass = val; } public set moveCount(val: ArrowOptions["moveCount"]) { this._moveCount = val; } public set moveByViewportSize(val: ArrowOptions["moveByViewportSize"]) { this._moveByViewportSize = val; } + public set interruptable(val: ArrowOptions["interruptable"]) { this._interruptable = val; } public constructor({ parentEl = null, @@ -55,7 +60,8 @@ class Arrow implements Plugin { nextElSelector = ARROW.NEXT_SELECTOR, disabledClass = ARROW.DISABLED_CLASS, moveCount = 1, - moveByViewportSize = false + moveByViewportSize = false, + interruptable = false }: Partial = {}) { this._parentEl = parentEl; this._prevElSelector = prevElSelector; @@ -63,6 +69,7 @@ class Arrow implements Plugin { this._disabledClass = disabledClass; this._moveCount = moveCount; this._moveByViewportSize = moveByViewportSize; + this._interruptable = interruptable; } public init(flicking: Flicking): void { @@ -73,6 +80,7 @@ class Arrow implements Plugin { this._flicking = flicking; flicking.on(EVENTS.MOVE, this._onAnimation); + flicking.on(EVENTS.WILL_CHANGE, this._onWillChange); const parentEl = this._parentEl ? this._parentEl : flicking.element; const prevEl = getElement(this._prevElSelector, parentEl, "Arrow"); @@ -100,6 +108,7 @@ class Arrow implements Plugin { } flicking.off(EVENTS.MOVE, this._onAnimation); + flicking.off(EVENTS.WILL_CHANGE, this._onWillChange); const prevEl = this._prevEl; const nextEl = this._nextEl; @@ -124,10 +133,16 @@ class Arrow implements Plugin { private _onPrevClick = () => { const flicking = this._flicking!; + const index = flicking.animating ? this._nextIndex : flicking.index; + const currentPanel = flicking.animating ? flicking.panels[this._nextIndex] : flicking.currentPanel; const camera = flicking.camera; const anchorPoints = camera.anchorPoints; - if (flicking.animating || anchorPoints.length <= 0) return; + if ((flicking.animating && !this.interruptable) || anchorPoints.length <= 0) return; + + if (flicking.animating) { + flicking.stopAnimation(); + } const firstAnchor = anchorPoints[0]; const moveCount = this._moveCount; @@ -137,18 +152,18 @@ class Arrow implements Plugin { .catch(this._onCatch); } else { if (flicking.circularEnabled) { - let targetPanel = flicking.currentPanel; + let targetPanel = currentPanel; for (let i = 0; i < moveCount; i++) { targetPanel = targetPanel.prev()!; } targetPanel.focus().catch(this._onCatch); - } else if (flicking.index > firstAnchor.panel.index) { - flicking.moveTo(Math.max(flicking.index - moveCount, firstAnchor.panel.index)) + } else if (index > firstAnchor.panel.index) { + flicking.moveTo(Math.max(index - moveCount, firstAnchor.panel.index)) .catch(this._onCatch); } else if (camera.position > camera.range.min) { - flicking.moveTo(flicking.index) + flicking.moveTo(index) .catch(this._onCatch); } } @@ -156,11 +171,16 @@ class Arrow implements Plugin { private _onNextClick = () => { const flicking = this._flicking!; - + const index = flicking.animating ? this._nextIndex : flicking.index; + const currentPanel = flicking.animating ? flicking.panels[this._nextIndex] : flicking.currentPanel; const camera = flicking.camera; const anchorPoints = camera.anchorPoints; - if (flicking.animating || anchorPoints.length <= 0) return; + if ((flicking.animating && !this.interruptable) || anchorPoints.length <= 0) return; + + if (flicking.animating) { + flicking.stopAnimation(); + } const lastAnchor = anchorPoints[anchorPoints.length - 1]; const moveCount = this._moveCount; @@ -170,18 +190,18 @@ class Arrow implements Plugin { .catch(this._onCatch); } else { if (flicking.circularEnabled) { - let targetPanel = flicking.currentPanel; + let targetPanel = currentPanel; for (let i = 0; i < moveCount; i++) { targetPanel = targetPanel.next()!; } targetPanel.focus().catch(this._onCatch); - } else if (flicking.index < lastAnchor.panel.index) { - flicking.moveTo(Math.min(flicking.index + moveCount, lastAnchor.panel.index)) + } else if (index < lastAnchor.panel.index) { + flicking.moveTo(Math.min(index + moveCount, lastAnchor.panel.index)) .catch(this._onCatch); } else if (camera.position > camera.range.min) { - flicking.moveTo(flicking.index) + flicking.moveTo(index) .catch(this._onCatch); } } @@ -199,6 +219,10 @@ class Arrow implements Plugin { } }; + private _onWillChange = (e: WillChangeEvent) => { + this._nextIndex = e.index; + }; + private _updateClass(pos: number) { const flicking = this._flicking!; const disabledClass = this._disabledClass; diff --git a/test/manual/arrow.html b/test/manual/arrow.html index ad71ad5..08912e8 100644 --- a/test/manual/arrow.html +++ b/test/manual/arrow.html @@ -15,16 +15,16 @@

Arrow

-
-
-
-
-
-
-
-
-
-
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
@@ -32,21 +32,21 @@

Arrow

Arrow "is-circle"

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
@@ -55,16 +55,16 @@

Arrow "is-outside"

-
-
-
-
-
-
-
-
-
-
+
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
diff --git a/test/manual/css/common.css b/test/manual/css/common.css index eecf86d..d88e16b 100644 --- a/test/manual/css/common.css +++ b/test/manual/css/common.css @@ -19,6 +19,10 @@ body { width: 200px; height: 200px; } +#arrow .card, #arrow2 .card, #arrow3 .card { + padding: 20px 30px; + font-size: 36px; +} #parallax .panel { width: 500px; position: relative; diff --git a/test/unit/Arrow.spec.ts b/test/unit/Arrow.spec.ts index 8e7ed2b..3e9717c 100644 --- a/test/unit/Arrow.spec.ts +++ b/test/unit/Arrow.spec.ts @@ -2,7 +2,7 @@ import Flicking from "@egjs/flicking"; import * as sinon from "sinon"; import Arrow from "../../src/Arrow"; -import { cleanup, createArrowFixture } from "./utils"; +import { cleanup, createArrowFixture, sandbox, tick, waitEvent } from "./utils"; describe("Arrow", () => { afterEach(() => { @@ -33,4 +33,70 @@ describe("Arrow", () => { return type === "touchstart" && options && (options as AddEventListenerOptions).passive; })).to.be.true; }); + + describe("Options", () => { + let flicking: Flicking; + + beforeEach(() => { + const wrapper = sandbox("flick"); + const viewportEl = document.createElement("div"); + viewportEl.style.width = "300px"; + viewportEl.className = "flicking-viewport"; + viewportEl.innerHTML = ` +
+
+
+
+
+ + + `; + wrapper.appendChild(viewportEl); + flicking = new Flicking(viewportEl, { duration: 1000 }); + }); + + afterEach(() => { + cleanup(); + flicking.destroy(); + }); + + describe("interruptable", () => { + it("should interrupt ongoing animation when interruptable is true", async () => { + // Given + const plugin = new Arrow({ interruptable: true }); + flicking.addPlugins(plugin); + await waitEvent(flicking, "ready"); + + // When + const nextArrow = flicking.element.querySelector(".flicking-arrow-next"); + + nextArrow?.dispatchEvent(new Event("click")); + tick(500); + nextArrow?.dispatchEvent(new Event("click")); + tick(2000); + + // Then + expect(flicking.index).to.be.equal(2); + }); + + it("should not interrupt ongoing animation when interruptable is true", async () => { + // Given + const plugin = new Arrow({ interruptable: false }); + flicking.addPlugins(plugin); + await waitEvent(flicking, "ready"); + + // When + const nextArrow = flicking.element.querySelector(".flicking-arrow-next"); + + nextArrow?.dispatchEvent(new Event("click")); + tick(500); + nextArrow?.dispatchEvent(new Event("click")); + tick(2000); + + // Then + expect(flicking.index).to.be.equal(1); + }); + }); + }); + }); From 8b8f9e14e2b2437b0b605ac9caeeb7422b79a521 Mon Sep 17 00:00:00 2001 From: malangfox Date: Sat, 29 Jun 2024 02:09:09 +0900 Subject: [PATCH 2/2] fix: add plugins after flicking is ready --- test/unit/Arrow.spec.ts | 4 ++-- test/unit/AutoPlay.spec.ts | 16 ++++++++-------- test/unit/Fade.spec.ts | 6 +++--- test/unit/Perspective.spec.ts | 8 ++++---- test/unit/Sync.spec.ts | 10 +++++----- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/test/unit/Arrow.spec.ts b/test/unit/Arrow.spec.ts index 3e9717c..490bd25 100644 --- a/test/unit/Arrow.spec.ts +++ b/test/unit/Arrow.spec.ts @@ -64,8 +64,8 @@ describe("Arrow", () => { it("should interrupt ongoing animation when interruptable is true", async () => { // Given const plugin = new Arrow({ interruptable: true }); - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); // When const nextArrow = flicking.element.querySelector(".flicking-arrow-next"); @@ -82,8 +82,8 @@ describe("Arrow", () => { it("should not interrupt ongoing animation when interruptable is true", async () => { // Given const plugin = new Arrow({ interruptable: false }); - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); // When const nextArrow = flicking.element.querySelector(".flicking-arrow-next"); diff --git a/test/unit/AutoPlay.spec.ts b/test/unit/AutoPlay.spec.ts index 7df1fdb..cb1720e 100644 --- a/test/unit/AutoPlay.spec.ts +++ b/test/unit/AutoPlay.spec.ts @@ -23,8 +23,8 @@ describe("AutoPlay", () => { const playSpy = sinon.spy(plugin, "play"); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); // Then expect(playSpy.calledOnce).to.be.true; @@ -39,8 +39,8 @@ describe("AutoPlay", () => { nextStub.resolves(void 0); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); // Then expect(nextStub.called).to.be.false; @@ -55,8 +55,8 @@ describe("AutoPlay", () => { const nextSpy = sinon.spy(flicking, "next"); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); // Then expect(nextSpy.called).to.be.false; @@ -94,8 +94,8 @@ describe("AutoPlay", () => { plugin.stop = stopSpy; // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); const wrapper = flicking.element; // Then @@ -113,8 +113,8 @@ describe("AutoPlay", () => { nextStub.resolves(void 0); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); const wrapper = flicking.element; // Then @@ -140,8 +140,8 @@ describe("AutoPlay", () => { nextStub.resolves(void 0); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); const wrapper = flicking.element; // Then @@ -205,8 +205,8 @@ describe("AutoPlay", () => { const flicking = new Flicking(createFlickingFixture()); // When - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); const wrapper = flicking.element; // Then @@ -245,8 +245,8 @@ describe("AutoPlay", () => { easing: x => x, duration: 1000 }); - flicking.addPlugins(plugin); await waitEvent(flicking, "ready"); + flicking.addPlugins(plugin); const flickingWrapper = flicking.element; await wait(500); diff --git a/test/unit/Fade.spec.ts b/test/unit/Fade.spec.ts index 7ad8965..2a9e555 100644 --- a/test/unit/Fade.spec.ts +++ b/test/unit/Fade.spec.ts @@ -29,8 +29,8 @@ describe("Fade", () => { it("should set opacity to 1 for current panel", async () => { // Given & When - flicking.addPlugins(new Fade()); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Fade()); // Then expect(flicking.currentPanel.element.style.opacity).to.equal("1"); @@ -38,8 +38,8 @@ describe("Fade", () => { it("should apply opacity to child elements if a selector is given", async () => { // Given & When - flicking.addPlugins(new Fade("p")); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Fade("p")); // Then const currentPanelEl = flicking.currentPanel.element; @@ -59,8 +59,8 @@ describe("Fade", () => { it("should be updated whenever flicking moves", async () => { // Given - flicking.addPlugins(new Fade()); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Fade()); // When void flicking.moveTo(1, 0); diff --git a/test/unit/Perspective.spec.ts b/test/unit/Perspective.spec.ts index 6848e17..71dfbbf 100644 --- a/test/unit/Perspective.spec.ts +++ b/test/unit/Perspective.spec.ts @@ -27,8 +27,8 @@ describe("Perspective", () => { it("should set transform to default for current panel", async () => { // Given & When - flicking.addPlugins(new Perspective()); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Perspective()); // Then expect(flicking.currentPanel.element.style.transform).to.equal("perspective(1000px) rotateX(0deg) rotateY(0deg) scale(1)"); @@ -36,8 +36,8 @@ describe("Perspective", () => { it("should set transform to default that except perspective for current panel when allocated other arguments", async () => { // Given & When - flicking.addPlugins(new Perspective({perspective: 500, rotate: 0.5, scale: 0.5})); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Perspective({perspective: 500, rotate: 0.5, scale: 0.5})); // Then expect(flicking.currentPanel.element.style.transform).to.equal("perspective(500px) rotateX(0deg) rotateY(0deg) scale(1)"); @@ -45,8 +45,8 @@ describe("Perspective", () => { it("should apply transform to child elements if a selector is given", async () => { // Given & When - flicking.addPlugins(new Perspective({selector: "p"})); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Perspective({selector: "p"})); // Then const currentPanelEl = flicking.currentPanel.element; @@ -66,8 +66,8 @@ describe("Perspective", () => { it("should be updated whenever flicking moves", async () => { // Given - flicking.addPlugins(new Perspective()); await waitEvent(flicking, "ready"); + flicking.addPlugins(new Perspective()); // When void flicking.moveTo(1, 0); diff --git a/test/unit/Sync.spec.ts b/test/unit/Sync.spec.ts index ef74556..2ad38c2 100644 --- a/test/unit/Sync.spec.ts +++ b/test/unit/Sync.spec.ts @@ -48,6 +48,7 @@ describe("Sync", () => { it("main flicking should move with other flickings", async () => { // Given + await waitEvent(flicking0, "ready"); flicking0.addPlugins(new Sync({ type: "camera", synchronizedFlickingOptions: [ @@ -59,7 +60,6 @@ describe("Sync", () => { } ] })); - await waitEvent(flicking0, "ready"); // When void flicking0.control.moveToPosition(500, 0); @@ -71,6 +71,7 @@ describe("Sync", () => { it("other flickings should move main flicking", async () => { // Given + await waitEvent(flicking1, "ready"); flicking0.addPlugins(new Sync({ type: "camera", synchronizedFlickingOptions: [ @@ -82,7 +83,6 @@ describe("Sync", () => { } ] })); - await waitEvent(flicking1, "ready"); // When void flicking1.control.moveToPosition(1100, 0); @@ -94,6 +94,7 @@ describe("Sync", () => { it("active panel should have active class", async () => { // Given + await waitEvent(flicking0, "ready"); flicking0.addPlugins(new Sync({ type: "index", synchronizedFlickingOptions: [ @@ -107,7 +108,6 @@ describe("Sync", () => { } ] })); - await waitEvent(flicking0, "ready"); // When void flicking0.moveTo(1, 0); @@ -121,6 +121,7 @@ describe("Sync", () => { it("slidable flicking should move other flickings", async () => { // Given + await waitEvent(flicking0, "ready"); flicking0.addPlugins(new Sync({ type: "index", synchronizedFlickingOptions: [ @@ -133,7 +134,6 @@ describe("Sync", () => { } ] })); - await waitEvent(flicking0, "ready"); // When void flicking0.moveTo(2, 0); @@ -146,6 +146,7 @@ describe("Sync", () => { it("clickable flicking should move other flickings", async () => { // Given + await waitEvent(flicking0, "ready"); flicking0.addPlugins(new Sync({ type: "index", synchronizedFlickingOptions: [ @@ -158,7 +159,6 @@ describe("Sync", () => { } ] })); - await waitEvent(flicking0, "ready"); // When await simulate(flicking0.panels[2].element, { deltaX: 0, deltaY: 0 });