@egjs/flicking
Version:
Everyday 30 million people experience. It's reliable, flexible and extendable carousel.
97 lines (77 loc) • 3.19 kB
text/typescript
/**
* Copyright (c) 2015 NAVER Corp.
* egjs projects are licensed under the MIT license
*/
import Snap from "./Snap";
import { MOVE_TYPE, EVENTS } from "../consts";
import { MoveTypeContext, DestinationInfo } from "../types";
import { circulate, clamp } 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, state, viewport } = ctx;
const destPos = axesEvent.destPos.flick;
const minimumDistanceToChange = this.calcBrinkOfChange(ctx);
const scrollArea = viewport.getScrollArea();
const currentPanel = viewport.getCurrentPanel()!;
const options = viewport.options;
const delta = Math.abs(axesEvent.delta.flick + state.delta);
if (delta > minimumDistanceToChange) {
const destInfo = super.findSnappedPanel(ctx);
destInfo.duration = axesEvent.duration;
destInfo.destPos = destPos;
destInfo.eventType = !options.circular && destInfo.panel === currentPanel
? ""
: EVENTS.CHANGE;
return destInfo;
} else {
let estimatedPosition = options.circular
? circulate(destPos, scrollArea.prev, scrollArea.next, false)
: destPos;
estimatedPosition = clamp(estimatedPosition, scrollArea.prev, scrollArea.next);
estimatedPosition += viewport.getRelativeHangerPosition();
const estimatedPanel = viewport.findNearestPanelAt(estimatedPosition)!;
return {
panel: estimatedPanel,
destPos,
duration: axesEvent.duration,
eventType: "",
};
}
}
public findRestorePanel(ctx: MoveTypeContext): DestinationInfo {
return this.findTargetPanel(ctx);
}
public findPanelWhenInterrupted(ctx: MoveTypeContext): DestinationInfo {
const { viewport } = ctx;
return {
panel: viewport.getNearestPanel()!,
destPos: viewport.getCameraPosition(),
duration: 0,
eventType: "",
};
}
protected calcBrinkOfChange(ctx: MoveTypeContext): number {
const { viewport, isNextDirection } = ctx;
const options = viewport.options;
const currentPanel = viewport.getCurrentPanel()!;
const halfGap = options.gap / 2;
const lastPosition = viewport.stateMachine.getState().lastPosition;
const currentPanelPosition = currentPanel.getPosition();
// As camera can stop anywhere in free scroll mode,
// minimumDistanceToChange should be calculated differently.
// Ref #191(https://github.com/naver/egjs-flicking/issues/191)
const lastHangerPosition = lastPosition + viewport.getRelativeHangerPosition();
const scrollAreaSize = viewport.getScrollAreaSize();
let minimumDistanceToChange = isNextDirection
? currentPanelPosition + currentPanel.getSize() - lastHangerPosition + halfGap
: lastHangerPosition - currentPanelPosition + halfGap;
minimumDistanceToChange = Math.abs(minimumDistanceToChange % scrollAreaSize);
return Math.min(minimumDistanceToChange, scrollAreaSize - minimumDistanceToChange);
}
}
export default FreeScroll;