Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MC-4951: Top/Bottom Binding Support #46

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "page-flip",
"name": "@mixam-platform/page-flip",
"version": "2.0.7",
"main": "dist/js/page-flip.browser.js",
"browser": "dist/js/page-flip.browser.js",
Expand All @@ -12,10 +12,12 @@
},
"publishConfig": {},
"homepage": "https://nodlik.github.io/StPageFlip/",
"dependencies": {},
"dependencies": {
"core-js": "^3.35.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^2.33.0",
"@typescript-eslint/parser": "^2.33.0",
"@typescript-eslint/eslint-plugin": "5.25.0",
"@typescript-eslint/parser": "5.25.0",
"css-loader": "^3.5.3",
"eslint": "^7.0.0",
"eslint-plugin-typescript": "^0.14.0",
Expand Down
File renamed without changes.
14 changes: 14 additions & 0 deletions src/BasicTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,23 @@ export interface PageRect {
height: number;
/** Page width. If portrait mode is equal to the width of the book. In landscape mode - half of the total width. */
pageWidth: number;
pageHeight: number;
}

/**
* Type representing a line segment contains two points: start and end
*/
export type Segment = [Point, Point];

export interface Box {
left: number;
top: number;
bottom: number;
right: number;
}

export interface ImageWithTrimData {
href: string;
trimBox: Box;
cropBox: Box;
}
11 changes: 6 additions & 5 deletions src/Collection/ImagePageCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ import { Render } from '../Render/Render';
import { PageCollection } from './PageCollection';
import { PageFlip } from '../PageFlip';
import { PageDensity } from '../Page/Page';
import { ImageWithTrimData } from '../BasicTypes';

/**
* Сlass representing a collection of pages as images on the canvas
*/
export class ImagePageCollection extends PageCollection {
private readonly imagesHref: string[];
private readonly imagesWithTrimData: ImageWithTrimData[];

constructor(app: PageFlip, render: Render, imagesHref: string[]) {
constructor(app: PageFlip, render: Render, images: ImageWithTrimData[]) {
super(app, render);

this.imagesHref = imagesHref;
this.imagesWithTrimData = images;
}

public load(): void {
for (const href of this.imagesHref) {
const page = new ImagePage(this.render, href, PageDensity.SOFT);
for (const imageWithTrimData of this.imagesWithTrimData) {
const page = new ImagePage(this.render, imageWithTrimData, PageDensity.SOFT);

page.load();
this.pages.push(page);
Expand Down
8 changes: 4 additions & 4 deletions src/Helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ export class Helper {
* @param {Segment} line2
*/
public static GetAngleBetweenTwoLine(line1: Segment, line2: Segment): number {
const A1 = line1[0].y - line1[1].y;
const A2 = line2[0].y - line2[1].y;
const A1 = line1[0].x - line1[1].x;
const A2 = line2[0].x - line2[1].x;

const B1 = line1[1].x - line1[0].x;
const B2 = line2[1].x - line2[0].x;
const B1 = line1[1].y - line1[0].y;
const B2 = line2[1].y - line2[0].y;

return Math.acos((A1 * A2 + B1 * B2) / (Math.sqrt(A1 * A1 + B1 * B1) * Math.sqrt(A2 * A2 + B2 * B2)));
}
Expand Down
97 changes: 85 additions & 12 deletions src/Page/ImagePage.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,39 @@
import { CanvasRender } from '../Render/CanvasRender';
import { Page, PageDensity, PageOrientation } from './Page';
import { Render } from '../Render/Render';
import { Point } from '../BasicTypes';
import { Box, ImageWithTrimData, Point } from '../BasicTypes';
import { BindingEdge } from '../Settings';

/**
* Class representing a book page as an image on Canvas
*/
export class ImagePage extends Page {
private readonly image: HTMLImageElement = null;
private readonly imageWithTrimData: ImageWithTrimData = null;
private isLoad = false;

private loadingAngle = 0;

constructor(render: Render, href: string, density: PageDensity) {
constructor(render: Render, image: ImageWithTrimData, density: PageDensity) {
super(render, density);


this.imageWithTrimData = image;

this.image = new Image();
this.image.src = href;
if (!image.href || image.href.trim() === '') {
this.image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+ip1sAAAAASUVORK5CYII=';
} else {
this.image.src = image.href;
}
}

public draw(tempDensity?: PageDensity): void {
public draw(tempDensity?: PageDensity, bindingEdge?: BindingEdge): void {
const ctx = (this.render as CanvasRender).getContext();

const pagePos = this.render.convertToGlobal(this.state.position);

const pageWidth = this.render.getRect().pageWidth;
const pageHeight = this.render.getRect().height;
const pageHeight = this.render.getRect().pageHeight;

ctx.save();
ctx.translate(pagePos.x, pagePos.y);
Expand All @@ -44,7 +53,27 @@ export class ImagePage extends Page {
if (!this.isLoad) {
this.drawLoader(ctx, { x: 0, y: 0 }, pageWidth, pageHeight);
} else {
ctx.drawImage(this.image, 0, 0, pageWidth, pageHeight);

if(this.imageWithTrimData.cropBox && this.imageWithTrimData.trimBox) {
const ratios = this.calculateCropToTrimRatios(this.imageWithTrimData.cropBox, this.imageWithTrimData.trimBox);

const trimWidth = this.imageWithTrimData.trimBox.right - this.imageWithTrimData.trimBox.left;
const trimHeight = this.imageWithTrimData.trimBox.bottom - this.imageWithTrimData.trimBox.top;
const isPortrait = trimHeight > trimWidth;
const aspectRatio = isPortrait ? trimWidth / trimHeight : trimHeight / trimWidth; // keep aspect ratio between 0-1 otherwise canvas gets stretched

const srcX = ratios.left * this.image.naturalWidth;
const srcY = ratios.top * this.image.naturalHeight;
const srcWidth = ratios.width * this.image.naturalWidth;
const srcHeight = ratios.height * this.image.naturalHeight;

ctx.drawImage(this.image,
srcX, srcY, srcWidth, srcHeight,
0, 0, pageWidth, pageHeight
);
} else {
ctx.drawImage(this.image, 0, 0, pageWidth, pageHeight);
}
}

ctx.restore();
Expand All @@ -54,17 +83,47 @@ export class ImagePage extends Page {
const rect = this.render.getRect();
const ctx = (this.render as CanvasRender).getContext();

const pageWidth = rect.pageWidth;
const pageHeight = rect.height;
const pageWidth = orient === PageOrientation.RIGHT || orient === PageOrientation.LEFT ? rect.pageWidth : rect.width;
const pageHeight = orient === PageOrientation.RIGHT || orient === PageOrientation.LEFT ? rect.height : rect.pageHeight;

const x = orient === PageOrientation.RIGHT ? rect.left + rect.pageWidth : rect.left;
//console.log(rect, orient);

const y = rect.top;
let x = orient === PageOrientation.RIGHT ? rect.left + rect.pageWidth : rect.left;
let y = rect.top;

if(orient === PageOrientation.TOP) {
x = rect.left;
y = rect.top;
}

if(orient === PageOrientation.BOTTOM) {
x = rect.left;
y = rect.top + rect.pageHeight;
}

if (!this.isLoad) {
this.drawLoader(ctx, { x, y }, pageWidth, pageHeight);
} else {
ctx.drawImage(this.image, x, y, pageWidth, pageHeight);

if(this.imageWithTrimData.cropBox && this.imageWithTrimData.trimBox) {
const ratios = this.calculateCropToTrimRatios(this.imageWithTrimData.cropBox, this.imageWithTrimData.trimBox);

const trimWidth = this.imageWithTrimData.trimBox.right - this.imageWithTrimData.trimBox.left;
const trimHeight = this.imageWithTrimData.trimBox.bottom - this.imageWithTrimData.trimBox.top;
const isPortrait = trimHeight > trimWidth;
const aspectRatio = isPortrait ? trimWidth / trimHeight : trimHeight / trimWidth; // keep aspect ratio between 0-1 otherwise canvas gets stretched

const srcX = ratios.left * this.image.naturalWidth;
const srcY = ratios.top * this.image.naturalHeight;
const srcWidth = ratios.width * this.image.naturalWidth;
const srcHeight = ratios.height * this.image.naturalHeight;

ctx.drawImage(this.image,
srcX, srcY, srcWidth, srcHeight,
x, y, pageWidth, pageHeight);
} else {
ctx.drawImage(this.image, x, y, pageWidth, pageHeight);
}
}
}

Expand Down Expand Up @@ -123,4 +182,18 @@ export class ImagePage extends Page {
public hideTemporaryCopy(): void {
return;
}

public calculateCropToTrimRatios(cropBox: Box, trimBox: Box): any {
const cropWidth = cropBox.right - cropBox.left;
const cropHeight = cropBox.bottom - cropBox.top;
const trimWidth = trimBox.right - trimBox.left;
const trimHeight = trimBox.bottom - trimBox.top;

return {
top: (trimBox.top - cropBox.top) / cropHeight,
left: (trimBox.left - cropBox.left) / cropWidth,
width: trimWidth / cropWidth,
height: trimHeight / cropHeight
};
}
}
9 changes: 8 additions & 1 deletion src/Page/Page.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Render } from '../Render/Render';
import { Point } from '../BasicTypes';
import { BindingEdge } from '../Settings';

/**
* State of the page on the basis of which rendering
Expand Down Expand Up @@ -27,6 +28,12 @@ export const enum PageOrientation {

/** Right side page */
RIGHT,

/** Top page */
TOP,

/** Bottom page */
BOTTOM
}

export const enum PageDensity {
Expand Down Expand Up @@ -78,7 +85,7 @@ export abstract class Page {
*
* @param {PageDensity} tempDensity - Density at the time of rendering
*/
public abstract draw(tempDensity?: PageDensity): void;
public abstract draw(tempDensity?: PageDensity, bindingEdge?: BindingEdge): void;

/**
* Page loading
Expand Down
26 changes: 19 additions & 7 deletions src/PageFlip.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PageCollection } from './Collection/PageCollection';
import { ImagePageCollection } from './Collection/ImagePageCollection';
import { HTMLPageCollection } from './Collection/HTMLPageCollection';
import { PageRect, Point } from './BasicTypes';
import { PageRect, Point, ImageWithTrimData } from './BasicTypes';
import { Flip, FlipCorner, FlippingState } from './Flip/Flip';
import { Orientation, Render } from './Render/Render';
import { CanvasRender } from './Render/CanvasRender';
Expand Down Expand Up @@ -68,17 +68,17 @@ export class PageFlip extends EventObject {
/**
* Load pages from images on the Canvas mode
*
* @param {string[]} imagesHref - List of paths to images
* @param {ImageWithTrimData[]} images - List of image with trim box data
*/
public loadFromImages(imagesHref: string[]): void {
public loadFromImages(images: ImageWithTrimData[]): 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 = new ImagePageCollection(this, this.render, images);
this.pages.load();

this.render.start();
Expand Down Expand Up @@ -127,13 +127,13 @@ export class PageFlip extends EventObject {
/**
* Update current pages from images
*
* @param {string[]} imagesHref - List of paths to images
* @param {ImageWithTrimData[]} images - List of image with trim box data
*/
public updateFromImages(imagesHref: string[]): void {
public updateFromImages(images: ImageWithTrimData[]): void {
const current = this.pages.getCurrentPageIndex();

this.pages.destroy();
this.pages = new ImagePageCollection(this, this.render, imagesHref);
this.pages = new ImagePageCollection(this, this.render, images);
this.pages.load();

this.pages.show(current);
Expand Down Expand Up @@ -252,6 +252,18 @@ export class PageFlip extends EventObject {
this.trigger('changeOrientation', this, newOrientation);
}

/**
* Call a page direction change event trigger. Update UI and rendering area
*
* @param {boolean} newRTL - New page direction
*/
public updateRTL(newRTL: boolean): void {
this.ui.setRTLStyle(newRTL);
this.update();
this.trigger('changeRTL', this, newRTL);
}


/**
* Get the total number of pages in a book
*
Expand Down
Loading