page-flip
Version:
Powerful, simple and flexible JS Library for creating realistic and beautiful page turning effect
400 lines (345 loc) • 10.9 kB
text/typescript
import { PageCollection } from './Collection/PageCollection';
import { ImagePageCollection } from './Collection/ImagePageCollection';
import { HTMLPageCollection } from './Collection/HTMLPageCollection';
import { PageRect, Point } from './BasicTypes';
import { Flip, FlipCorner, FlippingState } from './Flip/Flip';
import { Orientation, Render } from './Render/Render';
import { CanvasRender } from './Render/CanvasRender';
import { HTMLUI } from './UI/HTMLUI';
import { CanvasUI } from './UI/CanvasUI';
import { Helper } from './Helper';
import { Page } from './Page/Page';
import { EventObject } from './Event/EventObject';
import { HTMLRender } from './Render/HTMLRender';
import { FlipSetting, Settings } from './Settings';
import { UI } from './UI/UI';
import './Style/stPageFlip.css';
/**
* Class representing a main PageFlip object
*
* @extends EventObject
*/
export class PageFlip extends EventObject {
private mousePosition: Point;
private isUserTouch = false;
private isUserMove = false;
private readonly setting: FlipSetting = null;
private readonly block: HTMLElement; // Root HTML Element
private pages: PageCollection = null;
private flipController: Flip;
private render: Render;
private ui: UI;
/**
* Create a new PageFlip instance
*
* @constructor
* @param {HTMLElement} inBlock - Root HTML Element
* @param {Object} setting - Configuration object
*/
constructor(inBlock: HTMLElement, setting: Partial<FlipSetting>) {
super();
this.setting = new Settings().getSettings(setting);
this.block = inBlock;
}
/**
* Destructor. Remove a root HTML element and all event handlers
*/
public destroy(): void {
this.ui.destroy();
this.block.remove();
}
/**
* Update the render area. Re-show current page.
*/
public update(): void {
this.render.update();
this.pages.show();
}
/**
* Load pages from images on the Canvas mode
*
* @param {string[]} imagesHref - List of paths to images
*/
public loadFromImages(imagesHref: string[]): void {
this.ui = new CanvasUI(this.block, this, this.setting);
const canvas = (this.ui as CanvasUI).getCanvas();
this.render = new CanvasRender(this, this.setting, canvas);
this.flipController = new Flip(this.render, this);
this.pages = new ImagePageCollection(this, this.render, imagesHref);
this.pages.load();
this.render.start();
this.pages.show(this.setting.startPage);
// safari fix
setTimeout(() => {
this.ui.update();
this.trigger('init', this, {
page: this.setting.startPage,
mode: this.render.getOrientation(),
});
}, 1);
}
/**
* Load pages from HTML elements on the HTML mode
*
* @param {(NodeListOf<HTMLElement>|HTMLElement[])} items - List of pages as HTML Element
*/
public loadFromHTML(items: NodeListOf<HTMLElement> | HTMLElement[]): void {
this.ui = new HTMLUI(this.block, this, this.setting, items);
this.render = new HTMLRender(this, this.setting, this.ui.getDistElement());
this.flipController = new Flip(this.render, this);
this.pages = new HTMLPageCollection(this, this.render, this.ui.getDistElement(), items);
this.pages.load();
this.render.start();
this.pages.show(this.setting.startPage);
// safari fix
setTimeout(() => {
this.ui.update();
this.trigger('init', this, {
page: this.setting.startPage,
mode: this.render.getOrientation(),
});
}, 1);
}
/**
* Update current pages from images
*
* @param {string[]} imagesHref - List of paths to images
*/
public updateFromImages(imagesHref: string[]): void {
const current = this.pages.getCurrentPageIndex();
this.pages.destroy();
this.pages = new ImagePageCollection(this, this.render, imagesHref);
this.pages.load();
this.pages.show(current);
this.trigger('update', this, {
page: current,
mode: this.render.getOrientation(),
});
}
/**
* Update current pages from HTML
*
* @param {(NodeListOf<HTMLElement>|HTMLElement[])} items - List of pages as HTML Element
*/
public updateFromHtml(items: NodeListOf<HTMLElement> | HTMLElement[]): void {
const current = this.pages.getCurrentPageIndex();
this.pages.destroy();
this.pages = new HTMLPageCollection(this, this.render, this.ui.getDistElement(), items);
this.pages.load();
(this.ui as HTMLUI).updateItems(items);
this.render.reload();
this.pages.show(current);
this.trigger('update', this, {
page: current,
mode: this.render.getOrientation(),
});
}
/**
* Clear pages from HTML (remove to initinalState)
*/
public clear(): void {
this.pages.destroy();
(this.ui as HTMLUI).clear();
}
/**
* Turn to the previous page (without animation)
*/
public turnToPrevPage(): void {
this.pages.showPrev();
}
/**
* Turn to the next page (without animation)
*/
public turnToNextPage(): void {
this.pages.showNext();
}
/**
* Turn to the specified page number (without animation)
*
* @param {number} page - New page number
*/
public turnToPage(page: number): void {
this.pages.show(page);
}
/**
* Turn to the next page (with animation)
*
* @param {FlipCorner} corner - Active page corner when turning
*/
public flipNext(corner: FlipCorner = FlipCorner.TOP): void {
this.flipController.flipNext(corner);
}
/**
* Turn to the prev page (with animation)
*
* @param {FlipCorner} corner - Active page corner when turning
*/
public flipPrev(corner: FlipCorner = FlipCorner.TOP): void {
this.flipController.flipPrev(corner);
}
/**
* Turn to the specified page number (with animation)
*
* @param {number} page - New page number
* @param {FlipCorner} corner - Active page corner when turning
*/
public flip(page: number, corner: FlipCorner = FlipCorner.TOP): void {
this.flipController.flipToPage(page, corner);
}
/**
* Call a state change event trigger
*
* @param {FlippingState} newState - New state of the object
*/
public updateState(newState: FlippingState): void {
this.trigger('changeState', this, newState);
}
/**
* Call a page number change event trigger
*
* @param {number} newPage - New page Number
*/
public updatePageIndex(newPage: number): void {
this.trigger('flip', this, newPage);
}
/**
* Call a page orientation change event trigger. Update UI and rendering area
*
* @param {Orientation} newOrientation - New page orientation (portrait, landscape)
*/
public updateOrientation(newOrientation: Orientation): void {
this.ui.setOrientationStyle(newOrientation);
this.update();
this.trigger('changeOrientation', this, newOrientation);
}
/**
* Get the total number of pages in a book
*
* @returns {number}
*/
public getPageCount(): number {
return this.pages.getPageCount();
}
/**
* Get the index of the current page in the page list (starts at 0)
*
* @returns {number}
*/
public getCurrentPageIndex(): number {
return this.pages.getCurrentPageIndex();
}
/**
* Get page from collection by number
*
* @param {number} pageIndex
* @returns {Page}
*/
public getPage(pageIndex: number): Page {
return this.pages.getPage(pageIndex);
}
/**
* Get the current rendering object
*
* @returns {Render}
*/
public getRender(): Render {
return this.render;
}
/**
* Get current object responsible for flipping
*
* @returns {Flip}
*/
public getFlipController(): Flip {
return this.flipController;
}
/**
* Get current page orientation
*
* @returns {Orientation} Сurrent orientation: portrait or landscape
*/
public getOrientation(): Orientation {
return this.render.getOrientation();
}
/**
* Get current book sizes and position
*
* @returns {PageRect}
*/
public getBoundsRect(): PageRect {
return this.render.getRect();
}
/**
* Get configuration object
*
* @returns {FlipSetting}
*/
public getSettings(): FlipSetting {
return this.setting;
}
/**
* Get UI object
*
* @returns {UI}
*/
public getUI(): UI {
return this.ui;
}
/**
* Get current flipping state
*
* @returns {FlippingState}
*/
public getState(): FlippingState {
return this.flipController.getState();
}
/**
* Get page collection
*
* @returns {PageCollection}
*/
public getPageCollection(): PageCollection {
return this.pages;
}
/**
* Start page turning. Called when a user clicks or touches
*
* @param {Point} pos - Touch position in coordinates relative to the book
*/
public startUserTouch(pos: Point): void {
this.mousePosition = pos; // Save touch position
this.isUserTouch = true;
this.isUserMove = false;
}
/**
* Called when a finger / mouse moves
*
* @param {Point} pos - Touch position in coordinates relative to the book
* @param {boolean} isTouch - True if there was a touch event, not a mouse click
*/
public userMove(pos: Point, isTouch: boolean): void {
if (!this.isUserTouch && !isTouch && this.setting.showPageCorners) {
this.flipController.showCorner(pos); // fold Page Corner
} else if (this.isUserTouch) {
if (Helper.GetDistanceBetweenTwoPoint(this.mousePosition, pos) > 5) {
this.isUserMove = true;
this.flipController.fold(pos);
}
}
}
/**
* Сalled when the user has stopped touching
*
* @param {Point} pos - Touch end position in coordinates relative to the book
* @param {boolean} isSwipe - true if there was a mobile swipe event
*/
public userStop(pos: Point, isSwipe = false): void {
if (this.isUserTouch) {
this.isUserTouch = false;
if (!isSwipe) {
if (!this.isUserMove) this.flipController.flip(pos);
else this.flipController.stopMove();
}
}
}
}