@egjs/flicking 4.4.2 → 4.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TODO.md +3 -0
- package/declaration/Flicking.d.ts +15 -2
- package/declaration/camera/Camera.d.ts +28 -26
- package/declaration/camera/index.d.ts +2 -4
- package/declaration/camera/mode/BoundCameraMode.d.ts +13 -0
- package/declaration/camera/mode/CameraMode.d.ts +19 -0
- package/declaration/camera/mode/CircularCameraMode.d.ts +18 -0
- package/declaration/camera/mode/LinearCameraMode.d.ts +9 -0
- package/declaration/camera/mode/index.d.ts +6 -0
- package/declaration/const/external.d.ts +4 -0
- package/declaration/control/StrictControl.d.ts +1 -0
- package/declaration/core/AutoResizer.d.ts +3 -0
- package/declaration/core/ResizeWatcher.d.ts +33 -0
- package/declaration/renderer/Renderer.d.ts +13 -0
- package/declaration/type/external.d.ts +1 -3
- package/{css → dist/css}/flicking-inline.css +20 -13
- package/dist/css/flicking-inline.min.css +1 -0
- package/dist/css/flicking.css +44 -0
- package/dist/css/flicking.min.css +1 -0
- package/dist/flicking.esm.js +1491 -1251
- package/dist/flicking.esm.js.map +1 -1
- package/dist/flicking.js +1494 -1253
- package/dist/flicking.js.map +1 -1
- package/dist/flicking.min.js +2 -2
- package/dist/flicking.min.js.map +1 -1
- package/dist/flicking.pkgd.js +1466 -1225
- package/dist/flicking.pkgd.js.map +1 -1
- package/dist/flicking.pkgd.min.js +2 -2
- package/dist/flicking.pkgd.min.js.map +1 -1
- package/package.json +17 -7
- package/sass/flicking-inline.sass +30 -0
- package/sass/flicking.sass +23 -0
- package/src/Flicking.ts +127 -35
- package/src/camera/Camera.ts +162 -81
- package/src/camera/index.ts +3 -7
- package/src/camera/{BoundCamera.ts → mode/BoundCameraMode.ts} +46 -43
- package/src/camera/mode/CameraMode.ts +77 -0
- package/src/camera/mode/CircularCameraMode.ts +171 -0
- package/src/camera/mode/LinearCameraMode.ts +23 -0
- package/src/camera/mode/index.ts +14 -0
- package/src/cfc/sync.ts +29 -23
- package/src/cfc/withFlickingMethods.ts +3 -2
- package/src/const/external.ts +12 -0
- package/src/control/StrictControl.ts +10 -0
- package/src/core/AutoResizer.ts +33 -0
- package/src/core/ResizeWatcher.ts +133 -0
- package/src/renderer/Renderer.ts +92 -43
- package/css/flicking.css +0 -28
- package/declaration/camera/BoundCamera.d.ts +0 -9
- package/declaration/camera/CircularCamera.d.ts +0 -37
- package/declaration/camera/LinearCamera.d.ts +0 -5
- package/dist/flicking-inline.css +0 -2
- package/dist/flicking-inline.css.map +0 -1
- package/dist/flicking.css +0 -2
- package/dist/flicking.css.map +0 -1
- package/src/camera/CircularCamera.ts +0 -268
- package/src/camera/LinearCamera.ts +0 -35
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 NAVER Corp.
|
|
3
|
+
* egjs projects are licensed under the MIT license
|
|
4
|
+
*/
|
|
5
|
+
import Panel from "../../core/panel/Panel";
|
|
6
|
+
import AnchorPoint from "../../core/AnchorPoint";
|
|
7
|
+
import { DIRECTION } from "../../const/external";
|
|
8
|
+
import { circulatePosition } from "../../utils";
|
|
9
|
+
|
|
10
|
+
import CameraMode from "./CameraMode";
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* A {@link Camera} mode that connects the last panel and the first panel, enabling continuous loop
|
|
14
|
+
* @ko 첫번째 패널과 마지막 패널이 이어진 상태로, 무한히 회전할 수 있는 종류의 {@link Camera} 모드
|
|
15
|
+
*/
|
|
16
|
+
class CircularCameraMode extends CameraMode {
|
|
17
|
+
public checkAvailability(): boolean {
|
|
18
|
+
const flicking = this._flicking;
|
|
19
|
+
const renderer = flicking.renderer;
|
|
20
|
+
const panels = renderer.panels;
|
|
21
|
+
|
|
22
|
+
if (panels.length <= 0) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const firstPanel = panels[0];
|
|
27
|
+
const lastPanel = panels[panels.length - 1];
|
|
28
|
+
const firstPanelPrev = firstPanel.range.min - firstPanel.margin.prev;
|
|
29
|
+
const lastPanelNext = lastPanel.range.max + lastPanel.margin.next;
|
|
30
|
+
|
|
31
|
+
const visibleSize = flicking.camera.size;
|
|
32
|
+
const panelSizeSum = lastPanelNext - firstPanelPrev;
|
|
33
|
+
|
|
34
|
+
const canSetCircularMode = panels
|
|
35
|
+
.every(panel => panelSizeSum - panel.size >= visibleSize);
|
|
36
|
+
|
|
37
|
+
return canSetCircularMode;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
public getRange(): { min: number; max: number } {
|
|
41
|
+
const flicking = this._flicking;
|
|
42
|
+
const panels = flicking.renderer.panels;
|
|
43
|
+
|
|
44
|
+
if (panels.length <= 0) {
|
|
45
|
+
return { min: 0, max: 0 };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const firstPanel = panels[0];
|
|
49
|
+
const lastPanel = panels[panels.length - 1];
|
|
50
|
+
const firstPanelPrev = firstPanel.range.min - firstPanel.margin.prev;
|
|
51
|
+
const lastPanelNext = lastPanel.range.max + lastPanel.margin.next;
|
|
52
|
+
|
|
53
|
+
return { min: firstPanelPrev, max: lastPanelNext };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public getAnchors(): AnchorPoint[] {
|
|
57
|
+
const flicking = this._flicking;
|
|
58
|
+
const panels = flicking.renderer.panels;
|
|
59
|
+
|
|
60
|
+
return panels.map((panel, index) => new AnchorPoint({
|
|
61
|
+
index,
|
|
62
|
+
position: panel.position,
|
|
63
|
+
panel
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public findAnchorIncludePosition(position: number): AnchorPoint | null {
|
|
68
|
+
const camera = this._flicking.camera;
|
|
69
|
+
const range = camera.range;
|
|
70
|
+
const anchors = camera.anchorPoints;
|
|
71
|
+
const rangeDiff = camera.rangeDiff;
|
|
72
|
+
const anchorCount = anchors.length;
|
|
73
|
+
const positionInRange = circulatePosition(position, range.min, range.max);
|
|
74
|
+
|
|
75
|
+
let anchorInRange: AnchorPoint | null = super.findAnchorIncludePosition(positionInRange);
|
|
76
|
+
|
|
77
|
+
if (anchorCount > 0 && (position === range.min || position === range.max)) {
|
|
78
|
+
const possibleAnchors = [
|
|
79
|
+
anchorInRange,
|
|
80
|
+
new AnchorPoint({
|
|
81
|
+
index: 0,
|
|
82
|
+
position: anchors[0].position + rangeDiff,
|
|
83
|
+
panel: anchors[0].panel
|
|
84
|
+
}),
|
|
85
|
+
new AnchorPoint({
|
|
86
|
+
index: anchorCount - 1,
|
|
87
|
+
position: anchors[anchorCount - 1].position - rangeDiff,
|
|
88
|
+
panel: anchors[anchorCount - 1].panel
|
|
89
|
+
})
|
|
90
|
+
].filter(anchor => !!anchor) as AnchorPoint[];
|
|
91
|
+
|
|
92
|
+
anchorInRange = possibleAnchors.reduce((nearest: AnchorPoint | null, anchor) => {
|
|
93
|
+
if (!nearest) return anchor;
|
|
94
|
+
|
|
95
|
+
return Math.abs(nearest.position - position) < Math.abs(anchor.position - position)
|
|
96
|
+
? nearest
|
|
97
|
+
: anchor;
|
|
98
|
+
}, null);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!anchorInRange) return null;
|
|
102
|
+
|
|
103
|
+
if (position < range.min) {
|
|
104
|
+
const loopCount = -Math.floor((range.min - position) / rangeDiff) - 1;
|
|
105
|
+
|
|
106
|
+
return new AnchorPoint({
|
|
107
|
+
index: anchorInRange.index,
|
|
108
|
+
position: anchorInRange.position + rangeDiff * loopCount,
|
|
109
|
+
panel: anchorInRange.panel
|
|
110
|
+
});
|
|
111
|
+
} else if (position > range.max) {
|
|
112
|
+
const loopCount = Math.floor((position - range.max) / rangeDiff) + 1;
|
|
113
|
+
|
|
114
|
+
return new AnchorPoint({
|
|
115
|
+
index: anchorInRange.index,
|
|
116
|
+
position: anchorInRange.position + rangeDiff * loopCount,
|
|
117
|
+
panel: anchorInRange.panel
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return anchorInRange;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
public getCircularOffset(): number {
|
|
125
|
+
const flicking = this._flicking;
|
|
126
|
+
const camera = flicking.camera;
|
|
127
|
+
|
|
128
|
+
if (!camera.circularEnabled) return 0;
|
|
129
|
+
|
|
130
|
+
const toggled = flicking.panels.filter(panel => panel.toggled);
|
|
131
|
+
const toggledPrev = toggled.filter(panel => panel.toggleDirection === DIRECTION.PREV);
|
|
132
|
+
const toggledNext = toggled.filter(panel => panel.toggleDirection === DIRECTION.NEXT);
|
|
133
|
+
|
|
134
|
+
return this._calcPanelAreaSum(toggledPrev) - this._calcPanelAreaSum(toggledNext);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
public clampToReachablePosition(position: number): number {
|
|
138
|
+
// Basically all position is reachable for circular camera
|
|
139
|
+
return position;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
public canReach(panel: Panel): boolean {
|
|
143
|
+
if (panel.removed) return false;
|
|
144
|
+
|
|
145
|
+
// Always reachable on circular mode
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public canSee(panel: Panel): boolean {
|
|
150
|
+
const camera = this._flicking.camera;
|
|
151
|
+
const range = camera.range;
|
|
152
|
+
const rangeDiff = camera.rangeDiff;
|
|
153
|
+
const visibleRange = camera.visibleRange;
|
|
154
|
+
const visibleInCurrentRange = super.canSee(panel);
|
|
155
|
+
|
|
156
|
+
// Check looped visible area for circular case
|
|
157
|
+
if (visibleRange.min < range.min) {
|
|
158
|
+
return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min + rangeDiff, visibleRange.max + rangeDiff);
|
|
159
|
+
} else if (visibleRange.max > range.max) {
|
|
160
|
+
return visibleInCurrentRange || panel.isVisibleOnRange(visibleRange.min - rangeDiff, visibleRange.max - rangeDiff);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return visibleInCurrentRange;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private _calcPanelAreaSum(panels: Panel[]) {
|
|
167
|
+
return panels.reduce((sum: number, panel: Panel) => sum + panel.sizeIncludingMargin, 0);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export default CircularCameraMode;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 NAVER Corp.
|
|
3
|
+
* egjs projects are licensed under the MIT license
|
|
4
|
+
*/
|
|
5
|
+
import CameraMode from "./CameraMode";
|
|
6
|
+
|
|
7
|
+
class LinearCameraMode extends CameraMode {
|
|
8
|
+
public checkAvailability(): boolean {
|
|
9
|
+
// It's always available
|
|
10
|
+
return true;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public getRange(): { min: number; max: number } {
|
|
14
|
+
const renderer = this._flicking.renderer;
|
|
15
|
+
|
|
16
|
+
const firstPanel = renderer.getPanel(0);
|
|
17
|
+
const lastPanel = renderer.getPanel(renderer.panelCount - 1);
|
|
18
|
+
|
|
19
|
+
return { min: firstPanel?.position ?? 0, max: lastPanel?.position ?? 0 };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default LinearCameraMode;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import CameraMode from "./CameraMode";
|
|
2
|
+
import LinearCameraMode from "./LinearCameraMode";
|
|
3
|
+
import CircularCameraMode from "./CircularCameraMode";
|
|
4
|
+
import BoundCameraMode from "./BoundCameraMode";
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
LinearCameraMode,
|
|
8
|
+
CircularCameraMode,
|
|
9
|
+
BoundCameraMode
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export type {
|
|
13
|
+
CameraMode
|
|
14
|
+
};
|
package/src/cfc/sync.ts
CHANGED
|
@@ -2,12 +2,16 @@ import { DiffResult } from "@egjs/list-differ";
|
|
|
2
2
|
|
|
3
3
|
import Flicking from "../Flicking";
|
|
4
4
|
import Renderer from "../renderer/Renderer";
|
|
5
|
+
import Panel from "../core/panel/Panel";
|
|
5
6
|
|
|
6
7
|
export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]) => {
|
|
7
8
|
const renderer = flicking.renderer;
|
|
8
9
|
const panels = renderer.panels;
|
|
9
10
|
const prevList = [...diffResult.prevList];
|
|
10
11
|
|
|
12
|
+
const added: Panel[] = [];
|
|
13
|
+
const removed: Panel[] = [];
|
|
14
|
+
|
|
11
15
|
if (diffResult.removed.length > 0) {
|
|
12
16
|
let endIdx = -1;
|
|
13
17
|
let prevIdx = -1;
|
|
@@ -18,7 +22,7 @@ export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]
|
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
if (prevIdx >= 0 && removedIdx !== prevIdx - 1) {
|
|
21
|
-
batchRemove(renderer, prevIdx, endIdx + 1);
|
|
25
|
+
removed.push(...batchRemove(renderer, prevIdx, endIdx + 1));
|
|
22
26
|
|
|
23
27
|
endIdx = removedIdx;
|
|
24
28
|
prevIdx = removedIdx;
|
|
@@ -29,30 +33,30 @@ export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]
|
|
|
29
33
|
prevList.splice(removedIdx, 1);
|
|
30
34
|
});
|
|
31
35
|
|
|
32
|
-
batchRemove(renderer, prevIdx, endIdx + 1);
|
|
36
|
+
removed.push(...batchRemove(renderer, prevIdx, endIdx + 1));
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
diffResult.ordered.forEach(([
|
|
36
|
-
const prevPanel = panels[
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (indexDiff > 0) {
|
|
40
|
-
const middlePanels = panels.slice(prevIdx + 1, newIdx + 1);
|
|
41
|
-
|
|
42
|
-
prevPanel.increaseIndex(indexDiff);
|
|
43
|
-
middlePanels.forEach(panel => panel.decreaseIndex(1));
|
|
44
|
-
} else {
|
|
45
|
-
const middlePanels = panels.slice(newIdx, prevIdx);
|
|
46
|
-
|
|
47
|
-
prevPanel.decreaseIndex(-indexDiff);
|
|
48
|
-
middlePanels.forEach(panel => panel.increaseIndex(1));
|
|
49
|
-
}
|
|
50
|
-
// Update position
|
|
51
|
-
prevPanel.resize();
|
|
39
|
+
diffResult.ordered.forEach(([from, to]) => {
|
|
40
|
+
const prevPanel = panels.splice(from, 1)[0];
|
|
41
|
+
panels.splice(to, 0, prevPanel);
|
|
52
42
|
});
|
|
53
43
|
|
|
54
44
|
if (diffResult.ordered.length > 0) {
|
|
45
|
+
panels.forEach((panel, idx) => {
|
|
46
|
+
const indexDiff = idx - panel.index;
|
|
47
|
+
|
|
48
|
+
if (indexDiff > 0) {
|
|
49
|
+
panel.increaseIndex(indexDiff);
|
|
50
|
+
} else {
|
|
51
|
+
panel.decreaseIndex(-indexDiff);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
55
|
panels.sort((panel1, panel2) => panel1.index - panel2.index);
|
|
56
|
+
|
|
57
|
+
panels.forEach(panel => {
|
|
58
|
+
panel.updatePosition();
|
|
59
|
+
});
|
|
56
60
|
}
|
|
57
61
|
|
|
58
62
|
if (diffResult.added.length > 0) {
|
|
@@ -67,7 +71,7 @@ export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]
|
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
if (prevIdx >= 0 && addedIdx !== prevIdx + 1) {
|
|
70
|
-
batchInsert(renderer, diffResult, addedElements, startIdx, idx + 1);
|
|
74
|
+
added.push(...batchInsert(renderer, diffResult, addedElements, startIdx, idx + 1));
|
|
71
75
|
|
|
72
76
|
startIdx = -1;
|
|
73
77
|
prevIdx = -1;
|
|
@@ -77,13 +81,15 @@ export default (flicking: Flicking, diffResult: DiffResult<any>, rendered: any[]
|
|
|
77
81
|
});
|
|
78
82
|
|
|
79
83
|
if (startIdx >= 0) {
|
|
80
|
-
batchInsert(renderer, diffResult, addedElements, startIdx);
|
|
84
|
+
added.push(...batchInsert(renderer, diffResult, addedElements, startIdx));
|
|
81
85
|
}
|
|
82
86
|
}
|
|
87
|
+
|
|
88
|
+
renderer.updateAfterPanelChange(added, removed);
|
|
83
89
|
};
|
|
84
90
|
|
|
85
91
|
const batchInsert = (renderer: Renderer, diffResult: DiffResult<any>, addedElements: any[], startIdx: number, endIdx?: number) => {
|
|
86
|
-
renderer.
|
|
92
|
+
return renderer.batchInsertDefer(
|
|
87
93
|
...diffResult.added.slice(startIdx, endIdx).map((index, elIdx) => ({ index, elements: [addedElements[elIdx]], hasDOMInElements: false }))
|
|
88
94
|
);
|
|
89
95
|
};
|
|
@@ -91,6 +97,6 @@ const batchInsert = (renderer: Renderer, diffResult: DiffResult<any>, addedEleme
|
|
|
91
97
|
const batchRemove = (renderer: Renderer, startIdx: number, endIdx?: number) => {
|
|
92
98
|
const removed = renderer.panels.slice(startIdx, endIdx);
|
|
93
99
|
|
|
94
|
-
renderer.
|
|
100
|
+
return renderer.batchRemoveDefer({ index: startIdx, deleteCount: removed.length, hasDOMInElements: false });
|
|
95
101
|
};
|
|
96
102
|
|
|
@@ -19,7 +19,7 @@ import Flicking from "../Flicking";
|
|
|
19
19
|
*/
|
|
20
20
|
const withFlickingMethods = (prototype: any, flickingName: string) => {
|
|
21
21
|
[Component.prototype, Flicking.prototype].forEach(proto => {
|
|
22
|
-
Object.getOwnPropertyNames(proto).filter(name => !prototype[name] &&
|
|
22
|
+
Object.getOwnPropertyNames(proto).filter(name => !prototype[name] && name.indexOf("_") !== 0 && name !== "constructor")
|
|
23
23
|
.forEach((name: string) => {
|
|
24
24
|
const descriptor = Object.getOwnPropertyDescriptor(proto, name)!;
|
|
25
25
|
|
|
@@ -34,7 +34,8 @@ const withFlickingMethods = (prototype: any, flickingName: string) => {
|
|
|
34
34
|
const getterDescriptor: { get?: () => any; set?: (val: any) => void } = {};
|
|
35
35
|
if (descriptor.get) {
|
|
36
36
|
getterDescriptor.get = function() {
|
|
37
|
-
|
|
37
|
+
const flicking = this[flickingName];
|
|
38
|
+
return flicking && descriptor.get?.call(flicking);
|
|
38
39
|
};
|
|
39
40
|
}
|
|
40
41
|
if (descriptor.set) {
|
package/src/const/external.ts
CHANGED
|
@@ -98,3 +98,15 @@ export const CLASS = {
|
|
|
98
98
|
HIDDEN: "flicking-hidden",
|
|
99
99
|
DEFAULT_VIRTUAL: "flicking-panel"
|
|
100
100
|
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* An object with all possible {@link Flicking#circularFallback circularFallback}s
|
|
104
|
+
* @ko Flicking의 {@link Flicking#circularFallback circularFallback}에 설정 가능한 값들을 담고 있는 객체
|
|
105
|
+
* @type {object}
|
|
106
|
+
* @property {string} LINEAR "linear"
|
|
107
|
+
* @property {string} BOUND "bound"
|
|
108
|
+
*/
|
|
109
|
+
export const CIRCULAR_FALLBACK = {
|
|
110
|
+
LINEAR: "linear",
|
|
111
|
+
BOUND: "bound"
|
|
112
|
+
} as const;
|
|
@@ -141,6 +141,16 @@ class StrictControl extends Control {
|
|
|
141
141
|
return this;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
public async moveToPanel(panel: Panel, options: Parameters<Control["moveToPanel"]>[1]): Promise<void> {
|
|
145
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
146
|
+
const camera = flicking.camera;
|
|
147
|
+
const controller = this._controller;
|
|
148
|
+
|
|
149
|
+
controller.update(camera.controlParams);
|
|
150
|
+
|
|
151
|
+
return super.moveToPanel(panel, options);
|
|
152
|
+
}
|
|
153
|
+
|
|
144
154
|
/**
|
|
145
155
|
* Move {@link Camera} to the given position
|
|
146
156
|
* @ko {@link Camera}를 주어진 좌표로 이동합니다
|
package/src/core/AutoResizer.ts
CHANGED
|
@@ -8,6 +8,8 @@ class AutoResizer {
|
|
|
8
8
|
private _flicking: Flicking;
|
|
9
9
|
private _enabled: boolean;
|
|
10
10
|
private _resizeObserver: ResizeObserver | null;
|
|
11
|
+
private _resizeTimer: number;
|
|
12
|
+
private _maxResizeDebounceTimer: number;
|
|
11
13
|
|
|
12
14
|
public get enabled() { return this._enabled; }
|
|
13
15
|
|
|
@@ -15,6 +17,8 @@ class AutoResizer {
|
|
|
15
17
|
this._flicking = flicking;
|
|
16
18
|
this._enabled = false;
|
|
17
19
|
this._resizeObserver = null;
|
|
20
|
+
this._resizeTimer = -1;
|
|
21
|
+
this._maxResizeDebounceTimer = -1;
|
|
18
22
|
}
|
|
19
23
|
|
|
20
24
|
public enable(): this {
|
|
@@ -61,6 +65,35 @@ class AutoResizer {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
private _onResize = () => {
|
|
68
|
+
const flicking = this._flicking;
|
|
69
|
+
const resizeDebounce = flicking.resizeDebounce;
|
|
70
|
+
const maxResizeDebounce = flicking.maxResizeDebounce;
|
|
71
|
+
|
|
72
|
+
if (resizeDebounce <= 0) {
|
|
73
|
+
void flicking.resize();
|
|
74
|
+
} else {
|
|
75
|
+
if (this._maxResizeDebounceTimer <= 0) {
|
|
76
|
+
if (maxResizeDebounce > 0 && maxResizeDebounce >= resizeDebounce) {
|
|
77
|
+
this._maxResizeDebounceTimer = window.setTimeout(this._doScheduledResize, maxResizeDebounce);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (this._resizeTimer > 0) {
|
|
82
|
+
clearTimeout(this._resizeTimer);
|
|
83
|
+
this._resizeTimer = 0;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this._resizeTimer = window.setTimeout(this._doScheduledResize, resizeDebounce);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
private _doScheduledResize = () => {
|
|
91
|
+
clearTimeout(this._resizeTimer);
|
|
92
|
+
clearTimeout(this._maxResizeDebounceTimer);
|
|
93
|
+
|
|
94
|
+
this._maxResizeDebounceTimer = -1;
|
|
95
|
+
this._resizeTimer = -1;
|
|
96
|
+
|
|
64
97
|
void this._flicking.resize();
|
|
65
98
|
};
|
|
66
99
|
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 NAVER Corp.
|
|
3
|
+
* egjs projects are licensed under the MIT license
|
|
4
|
+
*/
|
|
5
|
+
import Component from "@egjs/component";
|
|
6
|
+
|
|
7
|
+
import { isString } from "../utils";
|
|
8
|
+
|
|
9
|
+
export interface ResizeWatherOptions {
|
|
10
|
+
resizeDebounce?: number;
|
|
11
|
+
maxResizeDebounce?: number;
|
|
12
|
+
useResizeObserver?: boolean;
|
|
13
|
+
useWindowResize?: boolean;
|
|
14
|
+
watchDirection?: "width" | "height" | "box" | false;
|
|
15
|
+
rectBox?: "border-box" | "content-box";
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class ResizeWatcher {
|
|
19
|
+
private _container: HTMLElement;
|
|
20
|
+
private _rect = { width: 0, height: 0 };
|
|
21
|
+
private _resizeTimer = 0;
|
|
22
|
+
private _maxResizeDebounceTimer = 0;
|
|
23
|
+
private _emitter: Component<{ resize: void }>;
|
|
24
|
+
private _observer: ResizeObserver | null;
|
|
25
|
+
private _options!: Required<ResizeWatherOptions>;
|
|
26
|
+
|
|
27
|
+
public constructor(container: HTMLElement | string, options: ResizeWatherOptions = {}) {
|
|
28
|
+
this._options = {
|
|
29
|
+
resizeDebounce: 100,
|
|
30
|
+
maxResizeDebounce: 0,
|
|
31
|
+
useResizeObserver: false,
|
|
32
|
+
useWindowResize: true,
|
|
33
|
+
watchDirection: false,
|
|
34
|
+
rectBox: "content-box",
|
|
35
|
+
...options
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
this._container = isString(container) ? document.querySelector<HTMLElement>(container)! : container;
|
|
39
|
+
this._init();
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public getRect() {
|
|
43
|
+
return this._rect;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public setRect(rect: { width: number; height: number }) {
|
|
47
|
+
this._rect = { ...rect };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public resize() {
|
|
51
|
+
const container = this._container;
|
|
52
|
+
|
|
53
|
+
this.setRect(this._options.rectBox === "border-box" ? {
|
|
54
|
+
width: container.offsetWidth,
|
|
55
|
+
height: container.offsetHeight
|
|
56
|
+
} : {
|
|
57
|
+
width: container.clientWidth,
|
|
58
|
+
height: container.clientHeight
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
public listen(callback: () => void) {
|
|
63
|
+
this._emitter.on("resize", callback);
|
|
64
|
+
return this;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
public destroy() {
|
|
68
|
+
this._observer?.disconnect();
|
|
69
|
+
if (this._options.useWindowResize) {
|
|
70
|
+
window.removeEventListener("reisze", this._onResize);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
private _init() {
|
|
75
|
+
const container = this._container;
|
|
76
|
+
const options = this._options;
|
|
77
|
+
|
|
78
|
+
this._emitter = new Component();
|
|
79
|
+
if (options.useResizeObserver && !!window.ResizeObserver) {
|
|
80
|
+
this._observer = new window.ResizeObserver(this._scheduleResize);
|
|
81
|
+
this._observer.observe(container, {
|
|
82
|
+
box: options.rectBox
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (options.useWindowResize) {
|
|
86
|
+
window.addEventListener("resize", this._scheduleResize);
|
|
87
|
+
}
|
|
88
|
+
this.resize();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
private _onResize = () => {
|
|
92
|
+
clearTimeout(this._resizeTimer);
|
|
93
|
+
clearTimeout(this._maxResizeDebounceTimer);
|
|
94
|
+
|
|
95
|
+
this._maxResizeDebounceTimer = 0;
|
|
96
|
+
this._resizeTimer = 0;
|
|
97
|
+
|
|
98
|
+
const watchDirection = this._options.watchDirection;
|
|
99
|
+
const prevRect = this._rect;
|
|
100
|
+
this.resize();
|
|
101
|
+
const rect = this._rect;
|
|
102
|
+
const isWatchWidth = watchDirection === "box" || watchDirection === "width";
|
|
103
|
+
const isWatchHeight = watchDirection === "box" || watchDirection === "height";
|
|
104
|
+
const isResize = !watchDirection
|
|
105
|
+
|| (isWatchWidth && prevRect.width !== rect.width)
|
|
106
|
+
|| (isWatchHeight && prevRect.height !== rect.height);
|
|
107
|
+
|
|
108
|
+
if (isResize) {
|
|
109
|
+
this._emitter.trigger("resize");
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
private _scheduleResize = () => {
|
|
114
|
+
const {
|
|
115
|
+
resizeDebounce,
|
|
116
|
+
maxResizeDebounce
|
|
117
|
+
} = this._options;
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if (!this._maxResizeDebounceTimer && maxResizeDebounce >= resizeDebounce) {
|
|
121
|
+
this._maxResizeDebounceTimer = window.setTimeout(this._onResize, maxResizeDebounce);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (this._resizeTimer) {
|
|
125
|
+
clearTimeout(this._resizeTimer);
|
|
126
|
+
this._resizeTimer = 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
this._resizeTimer = window.setTimeout(this._onResize, resizeDebounce);
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default ResizeWatcher;
|