UNPKG

@egjs/flicking

Version:

Everyday 30 million people experience. It's reliable, flexible and extendable carousel.

106 lines (86 loc) 3.32 kB
/** * Copyright (c) 2015 NAVER Corp. * egjs projects are licensed under the MIT license */ import State from "./State"; import { STATE_TYPE, EVENTS, DIRECTION } from "../consts"; import { FlickingContext } from "../types"; class HoldingState extends State { public readonly type = STATE_TYPE.HOLDING; public readonly holding = true; public readonly playing = true; private releaseEvent: any = null; public onChange(e: any, context: FlickingContext): void { const { flicking, triggerEvent, transitTo } = context; const offset = flicking.options.horizontal ? e.inputEvent.offsetX : e.inputEvent.offsetY; this.direction = offset < 0 ? DIRECTION.NEXT : DIRECTION.PREV; triggerEvent(EVENTS.MOVE_START, e, true) .onSuccess(() => { // Trigger DraggingState's onChange, to trigger "move" event immediately transitTo(STATE_TYPE.DRAGGING) .onChange(e, context); }) .onStopped(() => { transitTo(STATE_TYPE.DISABLED); }); } public onRelease(e: any, context: FlickingContext): void { const { viewport, triggerEvent, transitTo } = context; triggerEvent(EVENTS.HOLD_END, e, true); if (e.delta.flick !== 0) { // Sometimes "release" event on axes triggered before "change" event // Especially if user flicked panel fast in really short amount of time // if delta is not zero, that means above case happened. // Event flow should be HOLD_START -> MOVE_START -> MOVE -> HOLD_END // At least one move event should be included between holdStart and holdEnd e.setTo({ flick: viewport.getCameraPosition() }, 0); transitTo(STATE_TYPE.IDLE); return; } // Can't handle select event here, // As "finish" axes event happens this.releaseEvent = e; } public onFinish(e: any, { viewport, triggerEvent, transitTo }: FlickingContext): void { // Should transite to IDLE state before select event // As user expects hold is already finished transitTo(STATE_TYPE.IDLE); if (!this.releaseEvent) { return; } // Handle release event here // To prevent finish event called twice const releaseEvent = this.releaseEvent; // Static click const srcEvent = releaseEvent.inputEvent.srcEvent; let clickedElement: HTMLElement; if (srcEvent.type === "touchend") { const touchEvent = srcEvent as TouchEvent; const touch = touchEvent.changedTouches[0]; clickedElement = document.elementFromPoint(touch.clientX, touch.clientY) as HTMLElement; } else { clickedElement = srcEvent.target; } const clickedPanel = viewport.panelManager.findPanelOf(clickedElement); const cameraPosition = viewport.getCameraPosition(); if (clickedPanel) { const clickedPanelPosition = clickedPanel.getPosition(); const direction = clickedPanelPosition > cameraPosition ? DIRECTION.NEXT : clickedPanelPosition < cameraPosition ? DIRECTION.PREV : null; // Don't provide axes event, to use axes instance instead triggerEvent(EVENTS.SELECT, null, true, { direction, // Direction to the clicked panel index: clickedPanel.getIndex(), panel: clickedPanel, }); } } } export default HoldingState;