Skip to content

Commit

Permalink
fix: fix autoplay for freeScroll duration (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
daybrush committed Jul 12, 2023
1 parent 107f18c commit ed88689
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 17 deletions.
2 changes: 1 addition & 1 deletion jsdoc.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
},
"applicationName": "eg.Flicking",
"disqus": "egjs",
"googleAnalytics": "UA-70842526-17",
"googleAnalytics": "G-LWLTCXMENE",
"openGraph": {
"title": "",
"type": "website",
Expand Down
1 change: 1 addition & 0 deletions mocha.opts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
--timeout 10000
51 changes: 48 additions & 3 deletions src/AutoPlay.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import Flicking, { EVENTS, Plugin, DIRECTION } from "@egjs/flicking";
import Flicking, { EVENTS, Plugin, DIRECTION, MOVE_TYPE } from "@egjs/flicking";

interface AutoPlayOptions {
duration: number;
Expand Down Expand Up @@ -139,10 +139,55 @@ class AutoPlay implements Plugin {

this._playing = true;
this._timerId = window.setTimeout(() => {
let animationDuration = this._animationDuration || flicking.duration;
const moveType = flicking.moveType;
// for freeScroll
if (moveType === MOVE_TYPE.FREE_SCROLL || moveType?.[0] === MOVE_TYPE.FREE_SCROLL) {
const range = flicking.camera.range;
const cameraPosition = flicking.camera.position;
const currentPanel = flicking.currentPanel;
const prevPanel = currentPanel.prev();
const nextPanel = currentPanel.next();
const currentPosition = currentPanel.position;
let nextPosition = nextPanel?.position ?? range.max;
let prevPosition = prevPanel?.position ?? range.min;

// circular: prev (last) > cur (0) => prev(-1) < cur(0)
if (prevPosition > currentPosition) {
prevPosition = range.min - (range.max - prevPosition);
}
// current (last) > next (0)
if (nextPosition < currentPosition) {
nextPosition += range.max;
}
if (direction === DIRECTION.NEXT) {
// prev - cur - camera - next
const size = nextPosition - currentPosition;
let restSize = nextPosition - cameraPosition;

if (cameraPosition < currentPosition) {
// prev - camera - cur - next
restSize = nextPosition - cameraPosition;
}

animationDuration *= restSize / size;
} else {
// prev - caemra - cur - next
const size = currentPosition - prevPosition;
let restSize = cameraPosition - prevPosition;

if (cameraPosition > currentPosition) {
// prev - cur - camera - next
restSize = cameraPosition - prevPosition;
}
animationDuration *= restSize / size;
}
}

if (direction === DIRECTION.NEXT) {
flicking.next(this._animationDuration).catch(() => void 0);
flicking.next(animationDuration).catch(() => void 0);
} else {
flicking.prev(this._animationDuration).catch(() => void 0);
flicking.prev(animationDuration).catch(() => void 0);
}

this.play();
Expand Down
22 changes: 16 additions & 6 deletions test/manual/autoplay.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,29 @@
</head>
<body>
<h1>AutoPlay</h1>
<div id="autoplay" class="flick-container flicking-viewport">
<div id="autoplay" class="flick-container flicking-viewport autoplay">
<div class="flicking-camera">
<div class="panel"></div>
<div class="panel"></div>
<div class="panel"></div>
<div class="panel"></div>
<div class="panel"></div>
<div class="panel p1"></div>
<div class="panel p2"></div>
<div class="panel p3"></div>
<div class="panel p4"></div>
<div class="panel p5"></div>
</div>
</div>
<div>
<button id="play">Play</button>
<button id="stop">Stop</button>
</div>
<h2>freeScroll</h2>
<div id="autoplay2" class="flick-container flicking-viewport autoplay">
<div class="flicking-camera">
<div class="panel p1"></div>
<div class="panel p2"></div>
<div class="panel p3"></div>
<div class="panel p4"></div>
<div class="panel p5"></div>
</div>
</div>
<div>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc orci ante, placerat in nunc vel, cursus laoreet turpis. Quisque elementum turpis eget ligula condimentum gravida. Proin vulputate est arcu. Nunc elementum, massa a tempus dignissim, urna elit porttitor odio, in fringilla dolor metus finibus ante. Morbi sagittis finibus posuere. Interdum et malesuada fames ac ante ipsum primis in faucibus. Ut blandit, neque et scelerisque lacinia, libero ipsum dictum massa, eget cursus arcu turpis quis nunc. Proin rhoncus auctor arcu at bibendum. Aenean urna diam, cursus in lacus non, dignissim finibus purus. Nulla semper massa lorem, a elementum eros tempus et. Curabitur quis elit eget lorem bibendum ultrices sodales sit amet risus. Aenean ipsum justo, varius non pharetra eget, fermentum in sapien.

Expand Down
12 changes: 6 additions & 6 deletions test/manual/css/common.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ body {
overflow: hidden;
margin-right: 10px;
}
#autoplay .panel:after {
.autoplay .panel:after {
content: "";
position: relative;
display: block;
Expand All @@ -34,19 +34,19 @@ body {
background: #f55;
height: 120px
}
#autoplay .panel:nth-child(5n + 1):after {
.autoplay .panel.p1:after {
background: #F47071;
}
#autoplay .panel:nth-child(5n + 2):after {
.autoplay .panel.p2:after {
background: #F69462;
}
#autoplay .panel:nth-child(5n + 3):after {
.autoplay .panel.p3:after {
background: #EDE484;
}
#autoplay .panel:nth-child(5n + 4):after {
.autoplay .panel.p4:after {
background: #90F290;
}
#autoplay .panel:nth-child(5n + 5):after {
.autoplay .panel.p5:after {
background: #78CAFF;
}
.flick-container .panel img {
Expand Down
17 changes: 17 additions & 0 deletions test/manual/js/autoplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,20 @@ const flicking2 = new Flicking("#parallax", {
});

flicking2.addPlugins(new Flicking.Plugins.Parallax("img"));


const flicking3 = new Flicking("#autoplay2", {
align: "prev",
moveType: "freeScroll",
circular: true,
easing: x => x
// duration: 5000,
});

// AutoPlay
const autoplay3 = new Flicking.Plugins.AutoPlay({
direction: "prev",
duration: 0,
animationDuration: 1000
});
flicking3.addPlugins(autoplay3);
75 changes: 74 additions & 1 deletion test/unit/AutoPlay.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as sinon from "sinon";

import AutoPlay from "../../src/AutoPlay";

import { cleanup, createFlickingFixture, sandbox, tick, waitEvent } from "./utils";
import { createFlickingFixture, sandbox, tick, wait, waitEvent } from "./utils";

describe("AutoPlay", () => {
it("can receive older API of receiving duration and direction", () => {
Expand Down Expand Up @@ -216,4 +216,77 @@ describe("AutoPlay", () => {
wrapper.dispatchEvent(new Event("mouseleave"));
expect(plugin.playing).to.be.true;
});
(["PREV", "NEXT"] as const).forEach(direction => {
it(`should call resume ${direction} as much as the ratio-fixed duration when stop playing`, async () => {
// Given
const wrapper = sandbox("flick");
const viewportEl = document.createElement("div");
viewportEl.style.width = "199px";
viewportEl.className = "flicking-viewport";
viewportEl.innerHTML = `
<div class="flicking-camera">
<div class="flicking-panel-target" style="display: inline-block; width: 200px; height: 200px;"></div>
<div style="display: inline-block; width: 200px; height: 200px;"></div>
<div style="display: inline-block; width: 200px; height: 200px;"></div>
</div>
`;
wrapper.appendChild(viewportEl);

const plugin = new AutoPlay({
stopOnHover: true,
duration: 0,
direction,
animationDuration: 1000
});
const flicking = new Flicking(viewportEl, {
align: "prev",
moveType: "freeScroll",
circular: true,
easing: x => x,
duration: 1000
});
flicking.addPlugins(plugin);
await waitEvent(flicking, "ready");
const flickingWrapper = flicking.element;

await wait(500);
const target = flickingWrapper.querySelector(".flicking-panel-target")!;

// When
target.dispatchEvent(new MouseEvent("mousedown", {
buttons: 1,
clientX: 0,
clientY: 0,
bubbles: true,
cancelable: true
}));

// half (100) 0.5s
const halfIndex = flicking.currentPanel.index;

await wait(100);
target.dispatchEvent(new MouseEvent("mouseup", {
buttons: 1,
clientX: 0,
clientY: 0,
bubbles: true,
cancelable: true
}));
await wait(600);

// half (200) 0.5s
const nextIndex = flicking.currentPanel.index;

// Then
expect(halfIndex).to.be.equals(0);
if (direction === "PREV") {
// 0 => 2 (-1)
expect(nextIndex).to.be.equals(2);
} else {
// 0 => 1
expect(nextIndex).to.be.equals(1);
}
});

});
});
6 changes: 6 additions & 0 deletions test/unit/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,9 @@ export const simulate = (el: HTMLElement, option: Partial<{
export const waitEvent = (flicking: Flicking, eventName: typeof EVENTS[keyof typeof EVENTS]) => new Promise(res => {
flicking.once(eventName, res);
});


export const wait = (time = 100) => new Promise<void>(resolve => {
setTimeout(resolve, time);
tick(time);
});

0 comments on commit ed88689

Please sign in to comment.