Skip to content

Commit

Permalink
fix: apply ResizeObserver to camera and panels
Browse files Browse the repository at this point in the history
  • Loading branch information
malangfox committed Aug 21, 2024
1 parent 8e57219 commit a4761b8
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 4 deletions.
13 changes: 12 additions & 1 deletion src/Flicking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,13 @@ class Flicking extends Component<FlickingEvents> {
* @see Viewport
*/
public get viewport() { return this._viewport; }
/**
* {@link AutoResizer} instance of the Flicking
* @ko 현재 Flicking에 활성화된 {@link AutoResizer} 인스턴스
* @internal
* @readonly
*/
public get autoResizer() { return this._autoResizer; }
// Internal States
/**
* Whether Flicking's {@link Flicking#init init()} is called.
Expand Down Expand Up @@ -906,6 +913,10 @@ class Flicking extends Component<FlickingEvents> {
public set autoResize(val: FlickingOptions["autoResize"]) {
this._autoResize = val;

if (!this._initialized) {
return;
}

if (val) {
this._autoResizer.enable();
} else {
Expand All @@ -916,7 +927,7 @@ class Flicking extends Component<FlickingEvents> {
public set useResizeObserver(val: FlickingOptions["useResizeObserver"]) {
this._useResizeObserver = val;

if (this._autoResize) {
if (this._initialized && this._autoResize) {
this._autoResizer.enable();
}
}
Expand Down
17 changes: 16 additions & 1 deletion src/core/AutoResizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
*/
import Flicking from "../Flicking";

/**
* A component that detects size change and trigger resize method when the autoResize option is used
* @ko autoResize 옵션을 사용할 때 크기 변화를 감지하고 Flicking의 resize를 호출하는 컴포넌트
*/
class AutoResizer {
private _flicking: Flicking;
private _enabled: boolean;
Expand Down Expand Up @@ -36,7 +40,11 @@ class AutoResizer {
? new ResizeObserver(this._skipFirstResize)
: new ResizeObserver(this._onResize);

resizeObserver.observe(flicking.viewport.element);
[
flicking.viewport.element,
flicking.camera.element,
...flicking.panels.map(panel => panel.element)
].forEach((element) => { resizeObserver.observe(element); });

this._resizeObserver = resizeObserver;
} else {
Expand Down Expand Up @@ -64,6 +72,13 @@ class AutoResizer {
return this;
}

public observe(element: Element): this {
if (this._resizeObserver) {
this._resizeObserver.observe(element);
}
return this;
}

private _onResize = () => {
const flicking = this._flicking;
const resizeDebounce = flicking.resizeDebounce;
Expand Down
6 changes: 6 additions & 0 deletions src/renderer/Renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,12 @@ abstract class Renderer {
// Update camera & control
this._updateCameraAndControl();

if (flicking.autoResize && flicking.useResizeObserver) {
panelsAdded.forEach((panel) => {
flicking.autoResizer.observe(panel.element);
});
}

void this.render();

if (!flicking.animating) {
Expand Down
70 changes: 70 additions & 0 deletions test/unit/Flicking.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -908,6 +908,76 @@ describe("Flicking", () => {

expect(resizeSpy.calledOnce).to.be.true;
});

["viewport", "camera", "panel"].forEach(element => {
it(`should call resize when size of ${element} is changed`, async () => {
const flicking = await createFlicking(
El.viewport("1000px", "1000px").add(
El.camera("1000px", "1000px").add(
El.panel("800px", "1000px"),
El.panel("800px", "1000px"),
El.panel("800px", "1000px"),
)
),
{ autoResize: true, useResizeObserver: true }
);
const afterResizeSpy = sinon.spy();
const beforeResizeSpy = sinon.spy();

// wait for initial resize
await waitTime(100);

flicking.on(EVENTS.AFTER_RESIZE, afterResizeSpy);
flicking.on(EVENTS.BEFORE_RESIZE, beforeResizeSpy);

switch (element) {
case "viewport":
flicking.element.style.height = "3000px";
break;
case "camera":
flicking.camera.element.style.height = "3000px";
break;
case "panel":
flicking.panels[2].element.style.height = "3000px";
break;
}

await waitEvent(flicking, EVENTS.AFTER_RESIZE);

expect(afterResizeSpy.calledOnce).to.be.true;
expect(beforeResizeSpy.calledOnce).to.be.true;
});
});

it("should observe size of panel element if panel element is added later", async () => {
const flicking = await createFlicking(
El.viewport("1000px", "1000px").add(
El.camera("1000px", "1000px").add(
El.panel("800px", "1000px"),
El.panel("800px", "1000px"),
El.panel("800px", "1000px"),
)
),
{ autoResize: true, useResizeObserver: true }
);
const afterResizeSpy = sinon.spy();
const beforeResizeSpy = sinon.spy();

// wait for initial resize
await waitTime(100);

flicking.on(EVENTS.AFTER_RESIZE, afterResizeSpy);
flicking.on(EVENTS.BEFORE_RESIZE, beforeResizeSpy);

flicking.append(flicking.panels[0].element.outerHTML);

flicking.panels[3].element.style.height = "3000px";

await waitEvent(flicking, EVENTS.AFTER_RESIZE);

expect(afterResizeSpy.calledOnce).to.be.true;
expect(beforeResizeSpy.calledOnce).to.be.true;
});
});

describe("preventClickOnDrag", () => {
Expand Down
4 changes: 2 additions & 2 deletions test/unit/renderer/Renderer.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ describe("Renderer", () => {

it("should resize the panel with image when it's loaded", async () => {
const flicking = await createFlicking(El.viewport("200px", "200px").add(
El.camera().add(
El.camera("100%", "100%").add(
El.imgPanel("100%", "100%")
)
), { resizeOnContentsReady: true });
Expand All @@ -438,7 +438,7 @@ describe("Renderer", () => {

it("should update the camera range after the image's loaded", async () => {
const flicking = await createFlicking(El.viewport("200px", "200px").add(
El.camera().add(
El.camera("100%", "100%").add(
El.imgPanel("100%", "100%")
)
), { resizeOnContentsReady: true });
Expand Down

0 comments on commit a4761b8

Please sign in to comment.