@egjs/flicking 4.3.1 → 4.4.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/README.md +1 -1
- package/declaration/Flicking.d.ts +20 -11
- package/declaration/camera/Camera.d.ts +3 -2
- package/declaration/camera/CircularCamera.d.ts +2 -1
- package/declaration/const/error.d.ts +3 -1
- package/declaration/const/external.d.ts +5 -0
- package/declaration/core/AutoResizer.d.ts +13 -0
- package/declaration/core/VirtualManager.d.ts +37 -0
- package/declaration/core/index.d.ts +2 -1
- package/declaration/core/panel/ExternalPanel.d.ts +9 -5
- package/declaration/core/panel/Panel.d.ts +13 -7
- package/declaration/core/panel/VirtualPanel.d.ts +19 -0
- package/declaration/core/panel/index.d.ts +4 -3
- package/declaration/core/panel/provider/ElementProvider.d.ts +7 -0
- package/declaration/core/panel/provider/ExternalElementProvider.d.ts +8 -0
- package/declaration/core/panel/provider/VanillaElementProvider.d.ts +10 -0
- package/declaration/core/panel/provider/VirtualElementProvider.d.ts +13 -0
- package/declaration/core/panel/provider/index.d.ts +6 -0
- package/declaration/index.d.ts +11 -1
- package/declaration/renderer/ExternalRenderer.d.ts +1 -0
- package/declaration/renderer/Renderer.d.ts +17 -12
- package/declaration/renderer/VanillaRenderer.d.ts +2 -7
- package/declaration/renderer/index.d.ts +1 -0
- package/declaration/renderer/strategy/NormalRenderingStrategy.d.ts +25 -0
- package/declaration/renderer/strategy/RenderingStrategy.d.ts +15 -0
- package/declaration/renderer/strategy/VirtualRenderingStrategy.d.ts +17 -0
- package/declaration/renderer/strategy/index.d.ts +5 -0
- package/declaration/utils.d.ts +7 -1
- package/dist/flicking.esm.js +4583 -3686
- package/dist/flicking.esm.js.map +1 -1
- package/dist/flicking.js +4596 -3674
- 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 +10626 -9704
- 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 +1 -1
- package/src/Flicking.ts +130 -27
- package/src/camera/BoundCamera.ts +2 -2
- package/src/camera/Camera.ts +49 -26
- package/src/camera/CircularCamera.ts +23 -24
- package/src/camera/LinearCamera.ts +1 -1
- package/src/cfc/sync.ts +2 -2
- package/src/const/error.ts +6 -3
- package/src/const/external.ts +6 -0
- package/src/control/AxesController.ts +11 -6
- package/src/control/Control.ts +6 -6
- package/src/control/FreeControl.ts +2 -2
- package/src/control/SnapControl.ts +3 -3
- package/src/control/StrictControl.ts +2 -2
- package/src/core/AutoResizer.ts +81 -0
- package/src/core/VirtualManager.ts +188 -0
- package/src/core/index.ts +3 -1
- package/src/core/panel/ExternalPanel.ts +23 -15
- package/src/core/panel/Panel.ts +54 -34
- package/src/core/panel/VirtualPanel.ts +110 -0
- package/src/core/panel/index.ts +5 -4
- package/src/core/panel/provider/ElementProvider.ts +13 -0
- package/src/core/panel/provider/ExternalElementProvider.ts +15 -0
- package/src/core/panel/provider/VanillaElementProvider.ts +40 -0
- package/src/core/panel/provider/VirtualElementProvider.ts +45 -0
- package/src/core/panel/provider/index.ts +18 -0
- package/src/index.ts +12 -1
- package/src/index.umd.ts +2 -0
- package/src/renderer/ExternalRenderer.ts +36 -4
- package/src/renderer/Renderer.ts +106 -65
- package/src/renderer/VanillaRenderer.ts +28 -86
- package/src/renderer/index.ts +2 -0
- package/src/renderer/strategy/NormalRenderingStrategy.ts +109 -0
- package/src/renderer/strategy/RenderingStrategy.ts +21 -0
- package/src/renderer/strategy/VirtualRenderingStrategy.ts +110 -0
- package/src/renderer/strategy/index.ts +17 -0
- package/src/utils.ts +36 -2
- package/declaration/core/panel/ElementPanel.d.ts +0 -14
- package/declaration/exports.d.ts +0 -10
- package/src/core/panel/ElementPanel.ts +0 -52
- package/src/exports.ts +0 -16
package/src/renderer/Renderer.ts
CHANGED
|
@@ -10,10 +10,13 @@ import Panel, { PanelOptions } from "../core/panel/Panel";
|
|
|
10
10
|
import FlickingError from "../core/FlickingError";
|
|
11
11
|
import { ALIGN, EVENTS } from "../const/external";
|
|
12
12
|
import * as ERROR from "../const/error";
|
|
13
|
-
import { getFlickingAttached, getMinusCompensatedIndex, includes } from "../utils";
|
|
13
|
+
import { getFlickingAttached, getMinusCompensatedIndex, includes, parsePanelAlign } from "../utils";
|
|
14
|
+
|
|
15
|
+
import RenderingStrategy from "./strategy/RenderingStrategy";
|
|
14
16
|
|
|
15
17
|
export interface RendererOptions {
|
|
16
|
-
align
|
|
18
|
+
align?: FlickingOptions["align"];
|
|
19
|
+
strategy: RenderingStrategy;
|
|
17
20
|
}
|
|
18
21
|
|
|
19
22
|
/**
|
|
@@ -26,7 +29,8 @@ abstract class Renderer {
|
|
|
26
29
|
protected _panels: Panel[];
|
|
27
30
|
|
|
28
31
|
// Options
|
|
29
|
-
protected _align: RendererOptions["align"]
|
|
32
|
+
protected _align: NonNullable<RendererOptions["align"]>;
|
|
33
|
+
protected _strategy: RendererOptions["strategy"];
|
|
30
34
|
|
|
31
35
|
// Internal states Getter
|
|
32
36
|
/**
|
|
@@ -44,6 +48,10 @@ abstract class Renderer {
|
|
|
44
48
|
* @readonly
|
|
45
49
|
*/
|
|
46
50
|
public get panelCount() { return this._panels.length; }
|
|
51
|
+
/**
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
public get strategy() { return this._strategy; }
|
|
47
55
|
|
|
48
56
|
// Options Getter
|
|
49
57
|
/**
|
|
@@ -54,25 +62,28 @@ abstract class Renderer {
|
|
|
54
62
|
public get align() { return this._align; }
|
|
55
63
|
|
|
56
64
|
// Options Setter
|
|
57
|
-
public set align(val: RendererOptions["align"]) {
|
|
65
|
+
public set align(val: NonNullable<RendererOptions["align"]>) {
|
|
58
66
|
this._align = val;
|
|
59
67
|
|
|
60
|
-
const panelAlign =
|
|
68
|
+
const panelAlign = parsePanelAlign(val);
|
|
61
69
|
this._panels.forEach(panel => { panel.align = panelAlign; });
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
/**
|
|
65
73
|
* @param {object} options An options object<ko>옵션 오브젝트</ko>
|
|
66
|
-
* @param {Constants.ALIGN | string | number} [options.align] An {@link Flicking#align align} value that will be applied to all panels<ko>전체 패널에 적용될 {@link Flicking#align align} 값</ko>
|
|
74
|
+
* @param {Constants.ALIGN | string | number} [options.align="center"] An {@link Flicking#align align} value that will be applied to all panels<ko>전체 패널에 적용될 {@link Flicking#align align} 값</ko>
|
|
75
|
+
* @param {object} [options.strategy] An instance of RenderingStrategy(internal module)<ko>RenderingStrategy의 인스턴스(내부 모듈)</ko>
|
|
67
76
|
*/
|
|
68
77
|
public constructor({
|
|
69
|
-
align = ALIGN.CENTER
|
|
70
|
-
|
|
78
|
+
align = ALIGN.CENTER,
|
|
79
|
+
strategy
|
|
80
|
+
}: RendererOptions) {
|
|
71
81
|
this._flicking = null;
|
|
72
82
|
this._panels = [];
|
|
73
83
|
|
|
74
84
|
// Bind options
|
|
75
85
|
this._align = align;
|
|
86
|
+
this._strategy = strategy;
|
|
76
87
|
}
|
|
77
88
|
|
|
78
89
|
/**
|
|
@@ -87,12 +98,9 @@ abstract class Renderer {
|
|
|
87
98
|
* @return {this}
|
|
88
99
|
*/
|
|
89
100
|
public abstract render(): Promise<void>;
|
|
90
|
-
public abstract forceRenderAllPanels(): Promise<void>;
|
|
91
101
|
|
|
92
102
|
protected abstract _collectPanels(): void;
|
|
93
|
-
protected abstract _createPanel(el: any, options: PanelOptions): Panel;
|
|
94
|
-
protected abstract _insertPanelElements(panels: Panel[], nextSibling: Panel | null): void;
|
|
95
|
-
protected abstract _removePanelElements(panels: Panel[]): void;
|
|
103
|
+
protected abstract _createPanel(el: any, options: Omit<PanelOptions, "elementProvider">): Panel;
|
|
96
104
|
|
|
97
105
|
/**
|
|
98
106
|
* Initialize Renderer
|
|
@@ -128,6 +136,12 @@ abstract class Renderer {
|
|
|
128
136
|
return this._panels[index] || null;
|
|
129
137
|
}
|
|
130
138
|
|
|
139
|
+
public forceRenderAllPanels(): Promise<void> {
|
|
140
|
+
this._panels.forEach(panel => panel.markForShow());
|
|
141
|
+
|
|
142
|
+
return Promise.resolve();
|
|
143
|
+
}
|
|
144
|
+
|
|
131
145
|
/**
|
|
132
146
|
* Update all panel sizes
|
|
133
147
|
* @ko 모든 패널의 크기를 업데이트합니다
|
|
@@ -135,10 +149,16 @@ abstract class Renderer {
|
|
|
135
149
|
* @return {this}
|
|
136
150
|
*/
|
|
137
151
|
public updatePanelSize(): this {
|
|
138
|
-
const flicking = getFlickingAttached(this._flicking
|
|
152
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
153
|
+
const panels = this._panels;
|
|
154
|
+
|
|
155
|
+
if (panels.length <= 0) return this;
|
|
139
156
|
|
|
140
157
|
if (flicking.panelsPerView > 0) {
|
|
141
|
-
|
|
158
|
+
const firstPanel = panels[0];
|
|
159
|
+
firstPanel.resize();
|
|
160
|
+
|
|
161
|
+
this._updatePanelSizeByGrid(firstPanel, panels);
|
|
142
162
|
} else {
|
|
143
163
|
flicking.panels.forEach(panel => panel.resize());
|
|
144
164
|
}
|
|
@@ -151,19 +171,23 @@ abstract class Renderer {
|
|
|
151
171
|
* This will increase index of panels after by the number of panels added
|
|
152
172
|
* @ko 주어진 인덱스에 새로운 패널들을 추가합니다
|
|
153
173
|
* 해당 인덱스보다 같거나 큰 인덱스를 가진 기존 패널들은 추가한 패널의 개수만큼 인덱스가 증가합니다.
|
|
154
|
-
* @param {
|
|
155
|
-
* @param {
|
|
174
|
+
* @param {Array<object>} items An array of items to insert<ko>추가할 아이템들의 배열</ko>
|
|
175
|
+
* @param {number} [items.index] Index to insert new panels at<ko>새로 패널들을 추가할 인덱스</ko>
|
|
176
|
+
* @param {any[]} [items.elements] An array of element or framework component with element in it<ko>엘리먼트의 배열 혹은 프레임워크에서 엘리먼트를 포함한 컴포넌트들의 배열</ko>
|
|
177
|
+
* @param {boolean} [items.hasDOMInElements] Whether it contains actual DOM elements. If set to true, renderer will add them to the camera element<ko>내부에 실제 DOM 엘리먼트들을 포함하고 있는지 여부. true로 설정할 경우, 렌더러는 해당 엘리먼트들을 카메라 엘리먼트 내부에 추가합니다</ko>
|
|
156
178
|
* @return {Panel[]} An array of prepended panels<ko>추가된 패널들의 배열</ko>
|
|
157
179
|
*/
|
|
158
180
|
public batchInsert(...items: Array<{
|
|
159
181
|
index: number;
|
|
160
182
|
elements: any[];
|
|
183
|
+
hasDOMInElements: boolean;
|
|
161
184
|
}>): Panel[] {
|
|
162
185
|
const panels = this._panels;
|
|
163
|
-
const flicking = getFlickingAttached(this._flicking
|
|
186
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
164
187
|
|
|
165
188
|
const { control } = flicking;
|
|
166
|
-
const
|
|
189
|
+
const prevFirstPanel = panels[0];
|
|
190
|
+
const align = parsePanelAlign(this._align);
|
|
167
191
|
|
|
168
192
|
const allPanelsInserted = items.reduce((addedPanels, item) => {
|
|
169
193
|
const insertingIdx = getMinusCompensatedIndex(item.index, panels.length);
|
|
@@ -172,11 +196,19 @@ abstract class Renderer {
|
|
|
172
196
|
|
|
173
197
|
panels.splice(insertingIdx, 0, ...panelsInserted);
|
|
174
198
|
|
|
175
|
-
|
|
176
|
-
|
|
199
|
+
if (item.hasDOMInElements) {
|
|
200
|
+
// Insert the actual elements as camera element's children
|
|
201
|
+
this._insertPanelElements(panelsInserted, panelsPushed[0] ?? null);
|
|
202
|
+
}
|
|
177
203
|
|
|
178
204
|
// Resize the newly added panels
|
|
179
|
-
|
|
205
|
+
if (flicking.panelsPerView > 0) {
|
|
206
|
+
const firstPanel = prevFirstPanel || panelsInserted[0].resize();
|
|
207
|
+
|
|
208
|
+
this._updatePanelSizeByGrid(firstPanel, panelsInserted);
|
|
209
|
+
} else {
|
|
210
|
+
panelsInserted.forEach(panel => panel.resize());
|
|
211
|
+
}
|
|
180
212
|
|
|
181
213
|
// Update panel indexes & positions
|
|
182
214
|
panelsPushed.forEach(panel => {
|
|
@@ -219,13 +251,15 @@ abstract class Renderer {
|
|
|
219
251
|
* This will decrease index of panels after by the number of panels removed
|
|
220
252
|
* @ko 주어진 인덱스의 패널을 제거합니다
|
|
221
253
|
* 해당 인덱스보다 큰 인덱스를 가진 기존 패널들은 제거한 패널의 개수만큼 인덱스가 감소합니다
|
|
222
|
-
* @param {
|
|
223
|
-
* @param {number} [
|
|
254
|
+
* @param {Array<object>} items An array of items to remove<ko>제거할 아이템들의 배열</ko>
|
|
255
|
+
* @param {number} [items.index] Index of panel to remove<ko>제거할 패널의 인덱스</ko>
|
|
256
|
+
* @param {number} [items.deleteCount=1] Number of panels to remove from index<ko>`index` 이후로 제거할 패널의 개수</ko>
|
|
257
|
+
* @param {boolean} [items.hasDOMInElements=1] Whether it contains actual DOM elements. If set to true, renderer will remove them from the camera element<ko>내부에 실제 DOM 엘리먼트들을 포함하고 있는지 여부. true로 설정할 경우, 렌더러는 해당 엘리먼트들을 카메라 엘리먼트 내부에서 제거합니다</ko>
|
|
224
258
|
* @return An array of removed panels<ko>제거된 패널들의 배열</ko>
|
|
225
259
|
*/
|
|
226
|
-
public batchRemove(...items: Array<{ index: number; deleteCount: number }>): Panel[] {
|
|
260
|
+
public batchRemove(...items: Array<{ index: number; deleteCount: number; hasDOMInElements: boolean }>): Panel[] {
|
|
227
261
|
const panels = this._panels;
|
|
228
|
-
const flicking = getFlickingAttached(this._flicking
|
|
262
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
229
263
|
|
|
230
264
|
const { camera, control } = flicking;
|
|
231
265
|
const activePanel = control.activePanel;
|
|
@@ -246,14 +280,13 @@ abstract class Renderer {
|
|
|
246
280
|
panel.updatePosition();
|
|
247
281
|
});
|
|
248
282
|
|
|
249
|
-
|
|
283
|
+
if (item.hasDOMInElements) {
|
|
284
|
+
this._removePanelElements(panelsRemoved);
|
|
285
|
+
}
|
|
250
286
|
|
|
251
287
|
// Remove panel elements
|
|
252
288
|
panelsRemoved.forEach(panel => panel.destroy());
|
|
253
289
|
|
|
254
|
-
// Update camera & control
|
|
255
|
-
this._updateCameraAndControl();
|
|
256
|
-
|
|
257
290
|
if (includes(panelsRemoved, activePanel)) {
|
|
258
291
|
control.resetActive();
|
|
259
292
|
}
|
|
@@ -261,6 +294,9 @@ abstract class Renderer {
|
|
|
261
294
|
return [...removed, ...panelsRemoved];
|
|
262
295
|
}, []);
|
|
263
296
|
|
|
297
|
+
// Update camera & control
|
|
298
|
+
this._updateCameraAndControl();
|
|
299
|
+
|
|
264
300
|
void this.render();
|
|
265
301
|
|
|
266
302
|
// FIXME: fix for animating case
|
|
@@ -293,10 +329,11 @@ abstract class Renderer {
|
|
|
293
329
|
* @internal
|
|
294
330
|
*/
|
|
295
331
|
public checkPanelContentsReady(checkingPanels: Panel[]) {
|
|
296
|
-
const
|
|
332
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
333
|
+
const resizeOnContentsReady = flicking.resizeOnContentsReady;
|
|
297
334
|
const panels = this._panels;
|
|
298
335
|
|
|
299
|
-
if (!resizeOnContentsReady) return;
|
|
336
|
+
if (!resizeOnContentsReady || flicking.virtualEnabled) return;
|
|
300
337
|
|
|
301
338
|
const hasContents = (panel: Panel) => !!panel.element.querySelector("img, video");
|
|
302
339
|
checkingPanels = checkingPanels.filter(panel => hasContents(panel));
|
|
@@ -310,9 +347,7 @@ abstract class Renderer {
|
|
|
310
347
|
});
|
|
311
348
|
|
|
312
349
|
contentsReadyChecker.on("readyElement", e => {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if (!flicking) {
|
|
350
|
+
if (!this._flicking) {
|
|
316
351
|
// Renderer's destroy() is called before
|
|
317
352
|
contentsReadyChecker.destroy();
|
|
318
353
|
return;
|
|
@@ -362,16 +397,8 @@ abstract class Renderer {
|
|
|
362
397
|
contentsReadyChecker.check(checkingPanels.map(panel => panel.element));
|
|
363
398
|
}
|
|
364
399
|
|
|
365
|
-
protected _getPanelAlign() {
|
|
366
|
-
const align = this._align;
|
|
367
|
-
|
|
368
|
-
return typeof align === "object"
|
|
369
|
-
? (align as { panel: string | number }).panel
|
|
370
|
-
: align;
|
|
371
|
-
}
|
|
372
|
-
|
|
373
400
|
protected _updateCameraAndControl() {
|
|
374
|
-
const flicking = getFlickingAttached(this._flicking
|
|
401
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
375
402
|
const { camera, control } = flicking;
|
|
376
403
|
|
|
377
404
|
camera.updateRange();
|
|
@@ -380,16 +407,6 @@ abstract class Renderer {
|
|
|
380
407
|
control.updateInput();
|
|
381
408
|
}
|
|
382
409
|
|
|
383
|
-
protected _updateRenderingPanels(): void {
|
|
384
|
-
const flicking = getFlickingAttached(this._flicking, "Renderer");
|
|
385
|
-
|
|
386
|
-
if (flicking.renderOnlyVisible) {
|
|
387
|
-
this._showOnlyVisiblePanels(flicking);
|
|
388
|
-
} else {
|
|
389
|
-
flicking.panels.forEach(panel => panel.markForShow());
|
|
390
|
-
}
|
|
391
|
-
}
|
|
392
|
-
|
|
393
410
|
protected _showOnlyVisiblePanels(flicking: Flicking) {
|
|
394
411
|
const panels = flicking.renderer.panels;
|
|
395
412
|
const camera = flicking.camera;
|
|
@@ -408,12 +425,10 @@ abstract class Renderer {
|
|
|
408
425
|
panel.markForHide();
|
|
409
426
|
}
|
|
410
427
|
});
|
|
411
|
-
|
|
412
|
-
camera.updateOffset();
|
|
413
428
|
}
|
|
414
429
|
|
|
415
|
-
protected _updatePanelSizeByGrid(
|
|
416
|
-
const
|
|
430
|
+
protected _updatePanelSizeByGrid(referencePanel: Panel, panels: Panel[]) {
|
|
431
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
417
432
|
const panelsPerView = flicking.panelsPerView;
|
|
418
433
|
|
|
419
434
|
if (panelsPerView <= 0) {
|
|
@@ -421,12 +436,8 @@ abstract class Renderer {
|
|
|
421
436
|
}
|
|
422
437
|
if (panels.length <= 0) return;
|
|
423
438
|
|
|
424
|
-
// resize only the first panel
|
|
425
|
-
const firstPanel = panels[0];
|
|
426
|
-
firstPanel.resize();
|
|
427
|
-
|
|
428
439
|
const viewportSize = flicking.camera.size;
|
|
429
|
-
const gap =
|
|
440
|
+
const gap = referencePanel.margin.prev + referencePanel.margin.next;
|
|
430
441
|
|
|
431
442
|
const panelSize = (viewportSize - gap * (panelsPerView - 1)) / panelsPerView;
|
|
432
443
|
const panelSizeObj = flicking.horizontal
|
|
@@ -434,16 +445,46 @@ abstract class Renderer {
|
|
|
434
445
|
: { height: panelSize };
|
|
435
446
|
const firstPanelSizeObj = {
|
|
436
447
|
size: panelSize,
|
|
437
|
-
height:
|
|
438
|
-
margin:
|
|
448
|
+
height: referencePanel.height,
|
|
449
|
+
margin: referencePanel.margin
|
|
439
450
|
};
|
|
440
451
|
|
|
441
452
|
if (!flicking.noPanelStyleOverride) {
|
|
442
|
-
|
|
453
|
+
this._strategy.updatePanelSizes(flicking, panelSizeObj);
|
|
443
454
|
}
|
|
444
455
|
|
|
445
456
|
flicking.panels.forEach(panel => panel.resize(firstPanelSizeObj));
|
|
446
457
|
}
|
|
458
|
+
|
|
459
|
+
protected _removeAllChildsFromCamera() {
|
|
460
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
461
|
+
const cameraElement = flicking.camera.element;
|
|
462
|
+
|
|
463
|
+
// Remove other elements
|
|
464
|
+
while (cameraElement.firstChild) {
|
|
465
|
+
cameraElement.removeChild(cameraElement.firstChild);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
protected _insertPanelElements(panels: Panel[], nextSibling: Panel | null = null) {
|
|
470
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
471
|
+
const camera = flicking.camera;
|
|
472
|
+
const cameraElement = camera.element;
|
|
473
|
+
const nextSiblingElement = nextSibling?.element || null;
|
|
474
|
+
const fragment = document.createDocumentFragment();
|
|
475
|
+
|
|
476
|
+
panels.forEach(panel => fragment.appendChild(panel.element));
|
|
477
|
+
cameraElement.insertBefore(fragment, nextSiblingElement);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
protected _removePanelElements(panels: Panel[]) {
|
|
481
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
482
|
+
const cameraElement = flicking.camera.element;
|
|
483
|
+
|
|
484
|
+
panels.forEach(panel => {
|
|
485
|
+
cameraElement.removeChild(panel.element);
|
|
486
|
+
});
|
|
487
|
+
}
|
|
447
488
|
}
|
|
448
489
|
|
|
449
490
|
export default Renderer;
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { getFlickingAttached, toArray } from "../utils";
|
|
6
6
|
import Panel, { PanelOptions } from "../core/panel/Panel";
|
|
7
|
-
import ElementPanel from "../core/panel/ElementPanel";
|
|
8
7
|
|
|
9
8
|
import Renderer from "./Renderer";
|
|
10
9
|
|
|
@@ -14,112 +13,55 @@ import Renderer from "./Renderer";
|
|
|
14
13
|
class VanillaRenderer extends Renderer {
|
|
15
14
|
// eslint-disable-next-line @typescript-eslint/require-await
|
|
16
15
|
public async render() {
|
|
17
|
-
const flicking = getFlickingAttached(this._flicking
|
|
18
|
-
const
|
|
19
|
-
const wasRenderedPanels = this._panels.filter(panel => panel.element.parentElement === cameraEl);
|
|
20
|
-
|
|
21
|
-
this._updateRenderingPanels();
|
|
22
|
-
const renderingPanels = this._getRenderingPanelsByOrder();
|
|
23
|
-
|
|
24
|
-
this._removePanelElements(wasRenderedPanels.filter(panel => !panel.rendered));
|
|
25
|
-
this._insertPanelElements(renderingPanels.filter(panel => panel.element.parentElement !== cameraEl), null);
|
|
26
|
-
this._resetPanelElementOrder(renderingPanels);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/require-await
|
|
30
|
-
public async forceRenderAllPanels() {
|
|
31
|
-
const flicking = getFlickingAttached(this._flicking, "Renderer");
|
|
32
|
-
const camera = flicking.camera;
|
|
33
|
-
const cameraElement = camera.element;
|
|
34
|
-
const fragment = document.createDocumentFragment();
|
|
35
|
-
|
|
36
|
-
this._panels.forEach(panel => fragment.appendChild(panel.element));
|
|
16
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
17
|
+
const strategy = this._strategy;
|
|
37
18
|
|
|
38
|
-
|
|
19
|
+
strategy.updateRenderingPanels(flicking);
|
|
20
|
+
strategy.renderPanels(flicking);
|
|
39
21
|
|
|
40
|
-
|
|
22
|
+
this._resetPanelElementOrder();
|
|
41
23
|
}
|
|
42
24
|
|
|
43
25
|
protected _collectPanels() {
|
|
44
|
-
const flicking = getFlickingAttached(this._flicking
|
|
45
|
-
|
|
46
|
-
const cameraElement = flicking.camera.element;
|
|
47
|
-
|
|
48
|
-
// Remove all text nodes in the camera element
|
|
49
|
-
toArray(cameraElement.childNodes).forEach(node => {
|
|
50
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
51
|
-
cameraElement.removeChild(node);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
const align = this._getPanelAlign();
|
|
56
|
-
const cameraChilds = toArray(cameraElement.children);
|
|
57
|
-
|
|
58
|
-
this._panels = cameraChilds.map(
|
|
59
|
-
(el: HTMLElement, index: number) => new ElementPanel({ flicking, el, index, align })
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
protected _createPanel(el: HTMLElement, options: PanelOptions): ElementPanel {
|
|
64
|
-
return new ElementPanel({ el, ...options });
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
protected _insertPanelElements(panels: Panel[], nextSibling: Panel | null) {
|
|
68
|
-
const flicking = getFlickingAttached(this._flicking, "Renderer");
|
|
26
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
69
27
|
const camera = flicking.camera;
|
|
70
|
-
const cameraElement = camera.element;
|
|
71
|
-
const nextSiblingElement = nextSibling?.element || null;
|
|
72
|
-
const fragment = document.createDocumentFragment();
|
|
73
|
-
|
|
74
|
-
panels.forEach(panel => fragment.appendChild(panel.element));
|
|
75
|
-
cameraElement.insertBefore(fragment, nextSiblingElement);
|
|
76
28
|
|
|
77
|
-
|
|
29
|
+
this._removeAllTextNodes();
|
|
30
|
+
this._panels = this._strategy.collectPanels(flicking, camera.children);
|
|
78
31
|
}
|
|
79
32
|
|
|
80
|
-
protected
|
|
81
|
-
|
|
82
|
-
const cameraElement = flicking.camera.element;
|
|
83
|
-
|
|
84
|
-
panels.forEach(panel => {
|
|
85
|
-
cameraElement.removeChild(panel.element);
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
return this;
|
|
33
|
+
protected _createPanel(el: HTMLElement, options: Omit<PanelOptions, "elementProvider">): Panel {
|
|
34
|
+
return this._strategy.createPanel(el, options);
|
|
89
35
|
}
|
|
90
36
|
|
|
91
|
-
private _resetPanelElementOrder(
|
|
92
|
-
const flicking = getFlickingAttached(this._flicking
|
|
37
|
+
private _resetPanelElementOrder() {
|
|
38
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
93
39
|
const cameraEl = flicking.camera.element;
|
|
94
40
|
|
|
95
41
|
// We're using reversed panels here as last panel should be the last element of camera element
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
42
|
+
const reversedElements = this._strategy
|
|
43
|
+
.getRenderingElementsByOrder(flicking)
|
|
44
|
+
.reverse();
|
|
45
|
+
|
|
46
|
+
reversedElements.forEach((el, idx) => {
|
|
47
|
+
const nextEl = reversedElements[idx - 1] ? reversedElements[idx - 1] : null;
|
|
100
48
|
|
|
101
|
-
if (
|
|
102
|
-
cameraEl.insertBefore(
|
|
49
|
+
if (el.nextElementSibling !== nextEl) {
|
|
50
|
+
cameraEl.insertBefore(el, nextEl);
|
|
103
51
|
}
|
|
104
52
|
});
|
|
105
53
|
}
|
|
106
54
|
|
|
107
|
-
private
|
|
108
|
-
const flicking = getFlickingAttached(this._flicking
|
|
55
|
+
private _removeAllTextNodes() {
|
|
56
|
+
const flicking = getFlickingAttached(this._flicking);
|
|
109
57
|
const cameraElement = flicking.camera.element;
|
|
110
58
|
|
|
111
|
-
// Remove
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
private _getRenderingPanelsByOrder(): Panel[] {
|
|
118
|
-
const flicking = getFlickingAttached(this._flicking, "Renderer");
|
|
119
|
-
const panels = flicking.renderer.panels;
|
|
120
|
-
|
|
121
|
-
return panels.filter(panel => panel.rendered)
|
|
122
|
-
.sort((a, b) => (a.position + a.offset) - (b.position + b.offset));
|
|
59
|
+
// Remove all text nodes in the camera element
|
|
60
|
+
toArray(cameraElement.childNodes).forEach(node => {
|
|
61
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
62
|
+
cameraElement.removeChild(node);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
123
65
|
}
|
|
124
66
|
}
|
|
125
67
|
|
package/src/renderer/index.ts
CHANGED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 NAVER Corp.
|
|
3
|
+
* egjs projects are licensed under the MIT license
|
|
4
|
+
*/
|
|
5
|
+
import Flicking from "../../Flicking";
|
|
6
|
+
import Panel, { PanelOptions } from "../../core/panel/Panel";
|
|
7
|
+
import ElementProvider from "../../core/panel/provider/ElementProvider";
|
|
8
|
+
import { DIRECTION } from "../../const/external";
|
|
9
|
+
import { parsePanelAlign } from "../../utils";
|
|
10
|
+
|
|
11
|
+
import RenderingStrategy from "./RenderingStrategy";
|
|
12
|
+
|
|
13
|
+
export interface NormalRenderingStrategyOptions {
|
|
14
|
+
providerCtor: new (...args: any) => ElementProvider;
|
|
15
|
+
panelCtor: new (options: PanelOptions) => Panel;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NormalRenderingStrategy implements RenderingStrategy {
|
|
20
|
+
private _providerCtor: NormalRenderingStrategyOptions["providerCtor"];
|
|
21
|
+
private _panelCtor: NormalRenderingStrategyOptions["panelCtor"];
|
|
22
|
+
|
|
23
|
+
public constructor({ providerCtor, panelCtor }: NormalRenderingStrategyOptions) {
|
|
24
|
+
this._providerCtor = providerCtor;
|
|
25
|
+
this._panelCtor = panelCtor;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public renderPanels() {
|
|
29
|
+
// DO_NOTHING
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public getRenderingIndexesByOrder(flicking: Flicking) {
|
|
33
|
+
const renderedPanels = flicking.renderer.panels.filter(panel => panel.rendered);
|
|
34
|
+
const toggledPrev = renderedPanels.filter(panel => panel.toggled && panel.toggleDirection === DIRECTION.PREV);
|
|
35
|
+
const toggledNext = renderedPanels.filter(panel => panel.toggled && panel.toggleDirection === DIRECTION.NEXT);
|
|
36
|
+
const notToggled = renderedPanels.filter(panel => !panel.toggled);
|
|
37
|
+
|
|
38
|
+
return [...toggledPrev, ...notToggled, ...toggledNext].map(panel => panel.index);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public getRenderingElementsByOrder(flicking: Flicking) {
|
|
42
|
+
const panels = flicking.panels;
|
|
43
|
+
|
|
44
|
+
return this.getRenderingIndexesByOrder(flicking).map(index => panels[index].element);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public updateRenderingPanels(flicking: Flicking) {
|
|
48
|
+
if (flicking.renderOnlyVisible) {
|
|
49
|
+
this._showOnlyVisiblePanels(flicking);
|
|
50
|
+
} else {
|
|
51
|
+
flicking.panels.forEach(panel => panel.markForShow());
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public collectPanels(
|
|
56
|
+
flicking: Flicking,
|
|
57
|
+
elements: any[]
|
|
58
|
+
) {
|
|
59
|
+
const align = parsePanelAlign(flicking.renderer.align);
|
|
60
|
+
|
|
61
|
+
return elements.map((el, index) => new this._panelCtor({
|
|
62
|
+
index,
|
|
63
|
+
elementProvider: new this._providerCtor(el),
|
|
64
|
+
align,
|
|
65
|
+
flicking
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public createPanel(
|
|
70
|
+
element: any,
|
|
71
|
+
options: Omit<PanelOptions, "elementProvider">
|
|
72
|
+
) {
|
|
73
|
+
return new this._panelCtor({
|
|
74
|
+
...options,
|
|
75
|
+
elementProvider: new this._providerCtor(element)
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
public updatePanelSizes(flicking: Flicking, size: Partial<{
|
|
80
|
+
width: number | string;
|
|
81
|
+
height: number | string;
|
|
82
|
+
}>) {
|
|
83
|
+
flicking.panels.forEach(panel => panel.setSize(size));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private _showOnlyVisiblePanels(flicking: Flicking) {
|
|
87
|
+
const panels = flicking.renderer.panels;
|
|
88
|
+
const camera = flicking.camera;
|
|
89
|
+
|
|
90
|
+
const visibleIndexes = camera.visiblePanels.reduce((visibles, panel) => {
|
|
91
|
+
visibles[panel.index] = true;
|
|
92
|
+
return visibles;
|
|
93
|
+
}, {});
|
|
94
|
+
|
|
95
|
+
panels.forEach(panel => {
|
|
96
|
+
if (panel.index in visibleIndexes || panel.loading) {
|
|
97
|
+
panel.markForShow();
|
|
98
|
+
} else if (!flicking.holding) {
|
|
99
|
+
// During the input sequence,
|
|
100
|
+
// Do not remove panel elements as it won't trigger touchend event.
|
|
101
|
+
panel.markForHide();
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
camera.updateOffset();
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export default NormalRenderingStrategy;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2015 NAVER Corp.
|
|
3
|
+
* egjs projects are licensed under the MIT license
|
|
4
|
+
*/
|
|
5
|
+
import Flicking from "../../Flicking";
|
|
6
|
+
import Panel, { PanelOptions } from "../../core/panel/Panel";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
interface RenderingStrategy {
|
|
12
|
+
renderPanels(flicking: Flicking): void;
|
|
13
|
+
getRenderingIndexesByOrder(flicking: Flicking): number[];
|
|
14
|
+
getRenderingElementsByOrder(flicking: Flicking): HTMLElement[];
|
|
15
|
+
updateRenderingPanels(flicking: Flicking): void;
|
|
16
|
+
createPanel(element: any, options: Omit<PanelOptions, "elementProvider">): Panel;
|
|
17
|
+
collectPanels(flicking: Flicking, elements: any[]): Panel[];
|
|
18
|
+
updatePanelSizes(flicking: Flicking, size: Partial<{ width: number | string; height: number | string }>): void;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default RenderingStrategy;
|