Skip to content

Commit

Permalink
refactor: make classes for each move types
Browse files Browse the repository at this point in the history
  • Loading branch information
WoodNeck committed Apr 30, 2019
1 parent 2c95f4a commit a9043ec
Show file tree
Hide file tree
Showing 11 changed files with 413 additions and 213 deletions.
1 change: 1 addition & 0 deletions src/Flicking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ class Flicking extends Component {

viewport.moveTo(
targetPanel,
viewport.findEstimatedPosition(targetPanel),
eventType,
null,
duration,
Expand Down
6 changes: 4 additions & 2 deletions src/components/Panel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Panel implements FlickingPanel {
? ""
: EVENTS.CHANGE;

viewport.moveTo(this, eventType, null, duration);
viewport.moveTo(this, viewport.findEstimatedPosition(this), eventType, null, duration);
}

public update(updateFunction: (element: HTMLElement) => any): void {
Expand Down Expand Up @@ -321,7 +321,7 @@ class Panel implements FlickingPanel {
state.clonedPanels.forEach(panel => panel.state.index = index);
}

public setPosition(pos: number, virtual: boolean = false): void {
public setPosition(pos: number, virtual: boolean = false): this {
const state = this.state;
const options = this.viewport.options;
const elementStyle = this.element.style;
Expand All @@ -332,6 +332,8 @@ class Panel implements FlickingPanel {
? elementStyle.left = `${pos}px`
: elementStyle.top = `${pos}px`;
}

return this;
}

public clone(cloneIndex: number, virtual: boolean = false): Panel {
Expand Down
94 changes: 62 additions & 32 deletions src/components/Viewport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@ import Flicking from "../Flicking";
import Panel from "./Panel";
import PanelManager from "./PanelManager";
import StateMachine from "./StateMachine";
import MoveType from "../moves/MoveType";
import { FlickingOptions, FlickingPanel, FlickingStatus, ElementLike, EventType, TriggerCallback, NeedPanelEvent, FlickingEvent, MoveTypeObjectOption } from "../types";
import { DEFAULT_VIEWPORT_CSS, DEFAULT_CAMERA_CSS, TRANSFORM, DEFAULT_OPTIONS, EVENTS, DIRECTION, STATE_TYPE } from "../consts";
import { DEFAULT_VIEWPORT_CSS, DEFAULT_CAMERA_CSS, TRANSFORM, DEFAULT_OPTIONS, EVENTS, DIRECTION, STATE_TYPE, MOVE_TYPE } from "../consts";
import { clamp, applyCSS, toArray, parseArithmeticExpression, isBetween, isArray, parseElement } from "../utils";
import Snap from "../moves/Snap";
import FreeScroll from "../moves/FreeScroll";

export default class Viewport {
public options: FlickingOptions;
public stateMachine: StateMachine;
public panelManager: PanelManager;
public moveType: MoveType;

private flicking: Flicking;
private axes: Axes;
Expand Down Expand Up @@ -75,27 +79,23 @@ export default class Viewport {

public moveTo(
panel: Panel,
destPos: number,
eventType: EventType["CHANGE"] | EventType["RESTORE"] | "",
axesEvent: any,
duration: number = this.options.duration,
): TriggerCallback {
const state = this.state;
const currentState = this.stateMachine.getState();
const freeScroll = (this.options.moveType as MoveTypeObjectOption).type === "freeScroll";

const currentPosition = state.position;

let estimatedPosition = panel.getAnchorPosition() - state.relativeHangerPosition;
estimatedPosition = this.canSetBoundMode()
? clamp(estimatedPosition, state.scrollArea.prev, state.scrollArea.next)
: estimatedPosition;

const isTrusted = axesEvent
? axesEvent.isTrusted
: false;
const direction = estimatedPosition > currentPosition
? DIRECTION.NEXT
: DIRECTION.PREV;
const direction = destPos === currentPosition
? null
: destPos > currentPosition
? DIRECTION.NEXT
: DIRECTION.PREV;

let eventResult: TriggerCallback;
if (eventType === EVENTS.CHANGE) {
Expand All @@ -122,21 +122,23 @@ export default class Viewport {
currentState.delta = 0;
currentState.lastPosition = this.getCameraPosition();
currentState.targetPanel = panel;
currentState.direction = estimatedPosition > currentPosition
? DIRECTION.NEXT
: DIRECTION.PREV;
currentState.direction = destPos === currentPosition
? null
: destPos > currentPosition
? DIRECTION.NEXT
: DIRECTION.PREV;

if (estimatedPosition === currentPosition) {
if (destPos === currentPosition) {
// no move
this.nearestPanel = panel;
this.currentPanel = panel;
}

if (axesEvent && axesEvent.setTo) {
// freeScroll only occurs in release events
axesEvent.setTo({ flick: freeScroll ? axesEvent.destPos.flick : estimatedPosition }, duration);
axesEvent.setTo({ flick: destPos }, duration);
} else {
this.axes.setTo({ flick: estimatedPosition }, duration);
this.axes.setTo({ flick: destPos }, duration);
}
});

Expand Down Expand Up @@ -303,6 +305,17 @@ export default class Viewport {
}
}

public findEstimatedPosition(panel: Panel): number {
const scrollArea = this.getScrollArea();

let estimatedPosition = panel.getAnchorPosition() - this.getRelativeHangerPosition();
estimatedPosition = this.canSetBoundMode()
? clamp(estimatedPosition, scrollArea.prev, scrollArea.next)
: estimatedPosition;

return estimatedPosition;
}

public enable(): void {
this.panInput.enable();
}
Expand Down Expand Up @@ -600,6 +613,22 @@ export default class Viewport {
&& options.bound
&& (state.position <= scrollArea.prev || state.position >= scrollArea.next);
}

public canSetBoundMode(): boolean {
const state = this.state;
const options = this.options;
const lastPanel = this.panelManager.lastPanel();
if (!lastPanel) {
return false;
}

const summedPanelSize = lastPanel.getPosition() + lastPanel.getSize();

return options.bound
&& !options.circular
&& summedPanelSize >= state.size;
}

public getScrollAreaSize(): number {
const scrollArea = this.state.scrollArea;

Expand Down Expand Up @@ -643,6 +672,7 @@ export default class Viewport {

private build(): void {
this.applyCSSValue();
this.setMoveType();
this.setAxesInstance();
this.createPanels();
this.setDefaultPanel();
Expand Down Expand Up @@ -671,6 +701,21 @@ export default class Viewport {
}
}

private setMoveType(): void {
const moveType = this.options.moveType as MoveTypeObjectOption;

switch (moveType.type) {
case MOVE_TYPE.SNAP:
this.moveType = new Snap(moveType.count);
break;
case MOVE_TYPE.FREE_SCROLL:
this.moveType = new FreeScroll();
break;
default:
throw new Error("moveType is not correct!");
}
}

private setAxesInstance(): void {
const state = this.state;
const options = this.options;
Expand Down Expand Up @@ -782,21 +827,6 @@ export default class Viewport {
this.axes.setTo({ flick: defaultPosition }, 0);
}

private canSetBoundMode(): boolean {
const state = this.state;
const options = this.options;
const lastPanel = this.panelManager.lastPanel();
if (!lastPanel) {
return false;
}

const summedPanelSize = lastPanel.getPosition() + lastPanel.getSize();

return options.bound
&& !options.circular
&& summedPanelSize >= state.size;
}

private updateSize(): void {
const state = this.state;
const options = this.options;
Expand Down
8 changes: 8 additions & 0 deletions src/consts.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { FlickingOptions, EventType, Direction, AxesEventType, StateType, MoveTypeSnapOption, MoveTypeFreeScrollOption } from "./types";
import { checkTranslateSupport } from "./utils";

export const MOVE_TYPE: {
SNAP: "snap";
FREE_SCROLL: "freeScroll";
} = {
SNAP: "snap",
FREE_SCROLL: "freeScroll",
};

export const DEFAULT_MOVE_TYPE_OPTIONS: {
snap: MoveTypeSnapOption,
freeScroll: MoveTypeFreeScrollOption,
Expand Down
48 changes: 48 additions & 0 deletions src/moves/FreeScroll.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import Snap from "./Snap";
import { MOVE_TYPE, EVENTS } from "../consts";
import { MoveTypeContext, DestinationInfo } from "../types";
import { circulate } from "../utils";

class FreeScroll extends Snap {
protected readonly type: string = MOVE_TYPE.FREE_SCROLL;

constructor() {
// Set snap count to Infinity
super(Infinity);
}

public findTargetPanel(ctx: MoveTypeContext): DestinationInfo {
const { axesEvent, viewport, swipeDistance, minimumDistanceToChange } = ctx;
const destPos = axesEvent.destPos.flick;

const eventDelta = Math.abs(axesEvent.delta.flick);
if (eventDelta > minimumDistanceToChange) {
const destInfo = super.findSnappedPanel(ctx);
destInfo.destPos = destPos;
destInfo.eventType = destInfo.eventType === EVENTS.RESTORE
? ""
: EVENTS.CHANGE;

return destInfo;
} else {
const scrollArea = viewport.getScrollArea();
const estimatedPosition = circulate(destPos, scrollArea.prev, scrollArea.next, false)
+ viewport.getRelativeHangerPosition();

return {
panel: viewport.findNearestPanelAt(estimatedPosition)!,
destPos,
duration: viewport.options.duration,
eventType: swipeDistance > minimumDistanceToChange
? EVENTS.CHANGE
: "",
};
}
}

public findRestorePanel(ctx: MoveTypeContext): DestinationInfo {
return this.findTargetPanel(ctx);
}
}

export default FreeScroll;
45 changes: 45 additions & 0 deletions src/moves/MoveType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { MoveTypeStringOption, MoveTypeContext, DestinationInfo } from "../types";
import Panel from "../components/Panel";
import { EVENTS } from "../consts";

abstract class MoveType {
protected readonly abstract type: string;

public abstract findTargetPanel(ctx: MoveTypeContext): DestinationInfo;

public is(type: MoveTypeStringOption): boolean {
return type === this.type;
}

public findRestorePanel(ctx: MoveTypeContext): DestinationInfo {
const viewport = ctx.viewport;
const options = viewport.options;

const panel = options.circular
? this.findRestorePanelInCircularMode(ctx)
: viewport.getCurrentPanel()!;

return {
panel,
destPos: viewport.findEstimatedPosition(panel),
duration: options.duration,
eventType: EVENTS.RESTORE,
};
}

private findRestorePanelInCircularMode(ctx: MoveTypeContext): Panel {
const viewport = ctx.viewport;
const originalPanel = viewport.getCurrentPanel()!.getOriginalPanel();
const hangerPosition = viewport.getHangerPosition();

const firstClonedPanel = originalPanel.getIdenticalPanels()[1];
const lapped = Math.abs(originalPanel.getAnchorPosition() - hangerPosition)
> Math.abs(firstClonedPanel.getAnchorPosition() - hangerPosition);

return (!ctx.isNextDirection && lapped)
? firstClonedPanel
: originalPanel;
}
}

export default MoveType;
Loading

0 comments on commit a9043ec

Please sign in to comment.