@egjs/flicking 4.13.2-beta.0 → 4.13.2-beta.1

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.
@@ -33,8 +33,9 @@ abstract class CameraMode {
33
33
 
34
34
  public findAnchorIncludePosition(position: number): AnchorPoint | null {
35
35
  const anchors = this._flicking.camera.anchorPoints;
36
+ const anchorsIncludingPosition = anchors.filter(anchor => anchor.panel.includePosition(position, true));
36
37
 
37
- return anchors.reduce((nearest: AnchorPoint | null, anchor) => {
38
+ return anchorsIncludingPosition.reduce((nearest: AnchorPoint | null, anchor) => {
38
39
  if (!nearest) return anchor;
39
40
 
40
41
  return Math.abs(nearest.position - position) < Math.abs(anchor.position - position)
@@ -397,7 +397,7 @@ abstract class Control {
397
397
  }
398
398
  }
399
399
 
400
- protected _getPosition(panel: Panel, direction: ValueOf<typeof DIRECTION> = DIRECTION.NONE) {
400
+ private _getPosition(panel: Panel, direction: ValueOf<typeof DIRECTION> = DIRECTION.NONE) {
401
401
  const flicking = getFlickingAttached(this._flicking);
402
402
  const camera = flicking.camera;
403
403
 
@@ -9,7 +9,6 @@ import AnchorPoint from "../core/AnchorPoint";
9
9
  import { circulateIndex, clamp, getFlickingAttached } from "../utils";
10
10
  import * as AXES from "../const/axes";
11
11
  import * as ERROR from "../const/error";
12
- import { DIRECTION } from "../const/external";
13
12
 
14
13
  import Control from "./Control";
15
14
 
@@ -110,12 +109,7 @@ class SnapControl extends Control {
110
109
  if (snapDelta >= snapThreshold && snapDelta > 0) {
111
110
  // Move to anchor at position
112
111
  targetAnchor = this._findSnappedAnchor(position, anchorAtCamera);
113
- // const targetPanel = targetAnchor.panel;
114
- // const nextPosition = this._getPosition(targetPanel, DIRECTION.NEXT);
115
- // const prevPosition = this._getPosition(targetPanel, DIRECTION.PREV);
116
-
117
- // targetPosition = Math.abs(camera.position - nextPosition) < Math.abs(camera.position - prevPosition) ? nextPosition : prevPosition;
118
- } else if (absPosDelta >= flicking.threshold && absPosDelta > 0 && anchorAtCamera === activeAnchor) {
112
+ } else if (absPosDelta >= flicking.threshold && absPosDelta > 0) {
119
113
  // Move to the adjacent panel
120
114
  targetAnchor = this._findAdjacentAnchor(position, posDelta, anchorAtCamera);
121
115
  } else {
@@ -150,7 +144,6 @@ class SnapControl extends Control {
150
144
  throw new FlickingError(ERROR.MESSAGE.POSITION_NOT_REACHABLE(position), ERROR.CODE.POSITION_NOT_REACHABLE);
151
145
  }
152
146
 
153
- // console.log("_findSnappedAnchor", anchorAtPosition);
154
147
  if (!isFinite(count)) {
155
148
  return anchorAtPosition;
156
149
  }
@@ -2,8 +2,13 @@
2
2
  * Copyright (c) 2015 NAVER Corp.
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
+ import { getElementSize, getStyle } from "../utils";
5
6
  import Flicking from "../Flicking";
6
7
 
8
+ /**
9
+ * A component that detects size change and trigger resize method when the autoResize option is used
10
+ * @ko autoResize 옵션을 사용할 때 크기 변화를 감지하고 Flicking의 resize를 호출하는 컴포넌트
11
+ */
7
12
  class AutoResizer {
8
13
  private _flicking: Flicking;
9
14
  private _enabled: boolean;
@@ -11,7 +16,9 @@ class AutoResizer {
11
16
  private _resizeTimer: number;
12
17
  private _maxResizeDebounceTimer: number;
13
18
 
14
- public get enabled() { return this._enabled; }
19
+ public get enabled() {
20
+ return this._enabled;
21
+ }
15
22
 
16
23
  public constructor(flicking: Flicking) {
17
24
  this._flicking = flicking;
@@ -36,11 +43,15 @@ class AutoResizer {
36
43
  ? new ResizeObserver(this._skipFirstResize)
37
44
  : new ResizeObserver(this._onResize);
38
45
 
39
- resizeObserver.observe(flicking.viewport.element);
40
-
41
46
  this._resizeObserver = resizeObserver;
47
+
48
+ this.observe(flicking.viewport.element);
49
+
50
+ if (flicking.observePanelResize) {
51
+ this.observePanels();
52
+ }
42
53
  } else {
43
- window.addEventListener("resize", this._onResize);
54
+ window.addEventListener("resize", this._onResizeWrapper);
44
55
  }
45
56
 
46
57
  this._enabled = true;
@@ -48,6 +59,44 @@ class AutoResizer {
48
59
  return this;
49
60
  }
50
61
 
62
+ public observePanels(): this {
63
+ this._flicking.panels.forEach(panel => {
64
+ this.observe(panel.element);
65
+ });
66
+ return this;
67
+ }
68
+
69
+ public unobservePanels(): this {
70
+ this._flicking.panels.forEach(panel => {
71
+ this.unobserve(panel.element);
72
+ });
73
+ return this;
74
+ }
75
+
76
+ public observe(element: HTMLElement): this {
77
+ const resizeObserver = this._resizeObserver;
78
+
79
+ if (!resizeObserver) return this;
80
+
81
+ resizeObserver.observe(element);
82
+
83
+ return this;
84
+ }
85
+
86
+ public unobserve(element: HTMLElement): this {
87
+ const resizeObserver = this._resizeObserver;
88
+
89
+ if (!resizeObserver) return this;
90
+
91
+ resizeObserver.unobserve(element);
92
+
93
+ if (this._flicking.observePanelResize) {
94
+ this.unobservePanels();
95
+ }
96
+
97
+ return this;
98
+ }
99
+
51
100
  public disable(): this {
52
101
  if (!this._enabled) return this;
53
102
 
@@ -56,7 +105,7 @@ class AutoResizer {
56
105
  resizeObserver.disconnect();
57
106
  this._resizeObserver = null;
58
107
  } else {
59
- window.removeEventListener("resize", this._onResize);
108
+ window.removeEventListener("resize", this._onResizeWrapper);
60
109
  }
61
110
 
62
111
  this._enabled = false;
@@ -64,17 +113,64 @@ class AutoResizer {
64
113
  return this;
65
114
  }
66
115
 
67
- private _onResize = () => {
116
+ private _onResizeWrapper = () => {
117
+ this._onResize([]);
118
+ };
119
+
120
+ private _onResize = (entries: ResizeObserverEntry[]) => {
68
121
  const flicking = this._flicking;
69
122
  const resizeDebounce = flicking.resizeDebounce;
70
123
  const maxResizeDebounce = flicking.maxResizeDebounce;
71
124
 
125
+ const resizedViewportElement = flicking.element;
126
+ // 현재 구현에서 리사이즈 옵저빙 대상은 패널과 뷰포트 2개만 존재.
127
+ // 아래는 뷰포트만 변경되었을 때 동작해야하는 로직이 있으므로 아래와 같이 조건문을 건다.
128
+ // 패널 쪽에서는 리사이즈 감지에 resizeObserver를 사용하지 않는 경우가 없으므로 이 조건은 곧 뷰포트만 리사이즈가 된 경우를 의미한다.
129
+ const isResizedViewportOnly = entries.find(e => e.target === flicking.element) && entries.length === 1;
130
+
131
+ // 참고: resizeObserver를 사용하지 않은 경우에는 entries.length가 0으로 오는데 이 경우에는 그냥 항상 리사이즈가 진행되도록 한다.
132
+ // (vw, vh 등을 사용하는 경우 이상 동작이 발생할 여지가 있기 때문이다)
133
+ if (isResizedViewportOnly) {
134
+ // resize 이벤트가 발생했으나 이전과 width, height의 변화가 없다면 이후 로직을 진행하지 않는다.
135
+ const beforeSize = {
136
+ width: flicking.viewport.width,
137
+ height: flicking.viewport.height
138
+ };
139
+
140
+ const afterSize = {
141
+ width: getElementSize({
142
+ el: resizedViewportElement,
143
+ horizontal: true,
144
+ useFractionalSize: this._flicking.useFractionalSize,
145
+ useOffset: false,
146
+ style: getStyle(resizedViewportElement)
147
+ }),
148
+ height: getElementSize({
149
+ el: resizedViewportElement,
150
+ horizontal: false,
151
+ useFractionalSize: this._flicking.useFractionalSize,
152
+ useOffset: false,
153
+ style: getStyle(resizedViewportElement)
154
+ })
155
+ };
156
+
157
+ if (
158
+ beforeSize.height === afterSize.height &&
159
+ beforeSize.width === afterSize.width
160
+ ) {
161
+ return;
162
+ }
163
+ }
164
+
72
165
  if (resizeDebounce <= 0) {
73
166
  void flicking.resize();
74
167
  } else {
75
168
  if (this._maxResizeDebounceTimer <= 0) {
76
169
  if (maxResizeDebounce > 0 && maxResizeDebounce >= resizeDebounce) {
77
- this._maxResizeDebounceTimer = window.setTimeout(this._doScheduledResize, maxResizeDebounce);
170
+ this._maxResizeDebounceTimer = window.setTimeout(
171
+ this._doScheduledResize,
172
+ maxResizeDebounce
173
+ );
78
174
  }
79
175
  }
80
176
 
@@ -83,7 +179,10 @@ class AutoResizer {
83
179
  this._resizeTimer = 0;
84
180
  }
85
181
 
86
- this._resizeTimer = window.setTimeout(this._doScheduledResize, resizeDebounce);
182
+ this._resizeTimer = window.setTimeout(
183
+ this._doScheduledResize,
184
+ resizeDebounce
185
+ );
87
186
  }
88
187
  };
89
188
 
@@ -101,13 +200,13 @@ class AutoResizer {
101
200
  private _skipFirstResize = (() => {
102
201
  let isFirstResize = true;
103
202
 
104
- return (() => {
203
+ return (entries) => {
105
204
  if (isFirstResize) {
106
205
  isFirstResize = false;
107
206
  return;
108
207
  }
109
- this._onResize();
110
- });
208
+ this._onResize(entries);
209
+ };
111
210
  })();
112
211
  }
113
212
 
@@ -335,6 +335,19 @@ abstract class Renderer {
335
335
  // Update camera & control
336
336
  this._updateCameraAndControl();
337
337
 
338
+ if (flicking.autoResize && flicking.useResizeObserver) {
339
+ panelsAdded.forEach((panel) => {
340
+ if (panel.element) {
341
+ flicking.autoResizer.observe(panel.element);
342
+ }
343
+ });
344
+ panelsRemoved.forEach((panel) => {
345
+ if (panel.element) {
346
+ flicking.autoResizer.unobserve(panel.element);
347
+ }
348
+ });
349
+ }
350
+
338
351
  void this.render();
339
352
 
340
353
  if (!flicking.animating) {
package/src/utils.ts CHANGED
@@ -256,7 +256,12 @@ export const findIndex = <T>(array: T[], checker: (val: T) => boolean): number =
256
256
  export const getProgress = (pos: number, prev: number, next: number) => (pos - prev) / (next - prev);
257
257
 
258
258
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
259
- export const getStyle = (el: HTMLElement): CSSStyleDeclaration => window.getComputedStyle(el) || (el as any).currentStyle as CSSStyleDeclaration;
259
+ export const getStyle = (el: HTMLElement): CSSStyleDeclaration => {
260
+ if (!el) {
261
+ return {} as CSSStyleDeclaration;
262
+ }
263
+ return window.getComputedStyle(el) || (el as any).currentStyle as CSSStyleDeclaration;
264
+ };
260
265
 
261
266
  export const setSize = (el: HTMLElement, { width, height }: Partial<{
262
267
  width: number | string;