From da4149ed39078cbf4786a47571932095cceedb93 Mon Sep 17 00:00:00 2001 From: ashley-mixam <69148655+ashley-mixam@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:09:30 +0000 Subject: [PATCH 1/2] MC-4951: Top/Bottom Binding Support --- package.json | 10 ++- rollup.config.mjs | 24 ++++++ src/BasicTypes.ts | 14 ++++ src/Collection/ImagePageCollection.ts | 11 +-- src/Helper.ts | 8 +- src/Page/ImagePage.ts | 97 ++++++++++++++++++++--- src/Page/Page.ts | 9 ++- src/PageFlip.ts | 26 +++++-- src/Render/CanvasRender.ts | 41 ++++++---- src/Render/Render.ts | 107 ++++++++++++++++++++------ src/Settings.ts | 16 ++++ src/Style/stPageFlip.css | 8 ++ src/UI/UI.ts | 45 ++++++++--- 13 files changed, 334 insertions(+), 82 deletions(-) create mode 100644 rollup.config.mjs diff --git a/package.json b/package.json index bfc5cf5..d382074 100644 --- a/package.json +++ b/package.json @@ -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", @@ -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", diff --git a/rollup.config.mjs b/rollup.config.mjs new file mode 100644 index 0000000..d4d450a --- /dev/null +++ b/rollup.config.mjs @@ -0,0 +1,24 @@ +import typescript from 'rollup-plugin-typescript2'; +import postcss from 'rollup-plugin-postcss'; +import { terser } from 'rollup-plugin-terser'; + +export default [ + { + input: 'src/PageFlip.ts', + output: [{ file: 'dist/js/page-flip.browser.js', format: 'umd', name: 'St' }], + plugins: [ + postcss(), + typescript({ tsconfig: 'tsconfig.json', useTsconfigDeclarationDir: true }), + terser(), + ], + }, + { + input: 'src/PageFlip.ts', + output: [{ file: 'dist/js/page-flip.module.js', format: 'es' }], + plugins: [ + postcss(), + typescript({ tsconfig: 'tsconfig.json', useTsconfigDeclarationDir: true }), + terser(), + ], + }, +]; diff --git a/src/BasicTypes.ts b/src/BasicTypes.ts index 929a5fb..394b37a 100644 --- a/src/BasicTypes.ts +++ b/src/BasicTypes.ts @@ -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; +} \ No newline at end of file diff --git a/src/Collection/ImagePageCollection.ts b/src/Collection/ImagePageCollection.ts index a05e004..418fe7f 100644 --- a/src/Collection/ImagePageCollection.ts +++ b/src/Collection/ImagePageCollection.ts @@ -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); diff --git a/src/Helper.ts b/src/Helper.ts index d5ac4fc..fd254bd 100644 --- a/src/Helper.ts +++ b/src/Helper.ts @@ -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))); } diff --git a/src/Page/ImagePage.ts b/src/Page/ImagePage.ts index 536fe9d..056f97b 100644 --- a/src/Page/ImagePage.ts +++ b/src/Page/ImagePage.ts @@ -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); @@ -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(); @@ -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); + } } } @@ -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 + }; + } } diff --git a/src/Page/Page.ts b/src/Page/Page.ts index 288b402..c62c597 100644 --- a/src/Page/Page.ts +++ b/src/Page/Page.ts @@ -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 @@ -27,6 +28,12 @@ export const enum PageOrientation { /** Right side page */ RIGHT, + + /** Top page */ + TOP, + + /** Bottom page */ + BOTTOM } export const enum PageDensity { @@ -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 diff --git a/src/PageFlip.ts b/src/PageFlip.ts index 87fe9f2..ddc82b6 100644 --- a/src/PageFlip.ts +++ b/src/PageFlip.ts @@ -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'; @@ -68,9 +68,9 @@ 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(); @@ -78,7 +78,7 @@ export class PageFlip extends EventObject { 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(); @@ -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); @@ -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 * diff --git a/src/Render/CanvasRender.ts b/src/Render/CanvasRender.ts index 0629588..0b0f6ff 100644 --- a/src/Render/CanvasRender.ts +++ b/src/Render/CanvasRender.ts @@ -2,7 +2,7 @@ import { Orientation, Render } from './Render'; import { PageFlip } from '../PageFlip'; import { FlipDirection } from '../Flip/Flip'; import { PageOrientation } from '../Page/Page'; -import { FlipSetting } from '../Settings'; +import { BindingEdge, FlipSetting } from '../Settings'; /** * Class responsible for rendering the Canvas book @@ -29,16 +29,23 @@ export class CanvasRender extends Render { protected drawFrame(): void { this.clear(); - if (this.orientation !== Orientation.PORTRAIT) - if (this.leftPage != null) this.leftPage.simpleDraw(PageOrientation.LEFT); + if(this.setting.bindingEdge == BindingEdge.TOP_BOTTOM) { + if (this.orientation !== Orientation.PORTRAIT) + if (this.leftPage != null) this.leftPage.simpleDraw(PageOrientation.TOP); - if (this.rightPage != null) this.rightPage.simpleDraw(PageOrientation.RIGHT); + if (this.rightPage != null) this.rightPage.simpleDraw(PageOrientation.BOTTOM); + } else { + if (this.orientation !== Orientation.PORTRAIT) + if (this.leftPage != null) this.leftPage.simpleDraw(PageOrientation.LEFT); + + if (this.rightPage != null) this.rightPage.simpleDraw(PageOrientation.RIGHT); + } - if (this.bottomPage != null) this.bottomPage.draw(); + if (this.bottomPage != null) this.bottomPage.draw(undefined, this.setting.bindingEdge); - this.drawBookShadow(); + if(this.leftPage !== null && this.rightPage !== null) this.drawBookShadow(this.setting.bindingEdge); - if (this.flippingPage != null) this.flippingPage.draw(); + if (this.flippingPage != null) this.flippingPage.draw(undefined, this.setting.bindingEdge); if (this.shadow != null) { this.drawOuterShadow(); @@ -54,19 +61,22 @@ export class CanvasRender extends Render { } } - private drawBookShadow(): void { + private drawBookShadow(bindingEdge: BindingEdge): void { const rect = this.getRect(); this.ctx.save(); this.ctx.beginPath(); - const shadowSize = rect.width / 20; + const shadowSize = bindingEdge == BindingEdge.LEFT_RIGHT ? rect.width / 20 : rect.height / 20; this.ctx.rect(rect.left, rect.top, rect.width, rect.height); - const shadowPos = { x: rect.left + rect.width / 2 - shadowSize / 2, y: 0 }; + let shadowPos = { x: rect.left + rect.width / 2 - shadowSize / 2, y: 0 }; + if(bindingEdge == BindingEdge.TOP_BOTTOM) { + shadowPos = { y: rect.top + rect.height / 2 - shadowSize / 2, x: rect.left }; + } this.ctx.translate(shadowPos.x, shadowPos.y); - const outerGradient = this.ctx.createLinearGradient(0, 0, shadowSize, 0); + const outerGradient = this.ctx.createLinearGradient(0, 0, bindingEdge == BindingEdge.LEFT_RIGHT ? shadowSize : 0, bindingEdge == BindingEdge.LEFT_RIGHT ? 0 : shadowSize); outerGradient.addColorStop(0, 'rgba(0, 0, 0, 0)'); outerGradient.addColorStop(0.4, 'rgba(0, 0, 0, 0.2)'); @@ -78,7 +88,11 @@ export class CanvasRender extends Render { this.ctx.clip(); this.ctx.fillStyle = outerGradient; - this.ctx.fillRect(0, 0, shadowSize, rect.height * 2); + if(bindingEdge == BindingEdge.LEFT_RIGHT) { + this.ctx.fillRect(0, 0, shadowSize, rect.height * 2); + } else { + this.ctx.fillRect(0, 0, rect.width * 2, shadowSize); + } this.ctx.restore(); } @@ -161,7 +175,6 @@ export class CanvasRender extends Render { } private clear(): void { - this.ctx.fillStyle = 'white'; - this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); + this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height); } } diff --git a/src/Render/Render.ts b/src/Render/Render.ts index 927ee52..2432e2e 100644 --- a/src/Render/Render.ts +++ b/src/Render/Render.ts @@ -2,7 +2,7 @@ import { PageFlip } from '../PageFlip'; import { Point, PageRect, RectPoints } from '../BasicTypes'; import { FlipDirection } from '../Flip/Flip'; import { Page, PageOrientation } from '../Page/Page'; -import { FlipSetting, SizeType } from '../Settings'; +import { BindingEdge, FlipSetting, SizeType } from '../Settings'; type FrameAction = () => void; type AnimationSuccessAction = () => void; @@ -71,6 +71,7 @@ export abstract class Render { protected direction: FlipDirection = null; /** Current book orientation */ protected orientation: Orientation = null; + protected rtl: boolean = null; /** Сurrent state of the shadows */ protected shadow: Shadow = null; /** Сurrent animation process */ @@ -191,11 +192,17 @@ export abstract class Render { public update(): void { this.boundsRect = null; const orientation = this.calculateBoundsRect(); + const rtl = this.app.getSettings().rtl; if (this.orientation !== orientation) { this.orientation = orientation; this.app.updateOrientation(orientation); } + + if (this.rtl !== rtl) { + this.rtl = rtl; + this.app.updateRTL(rtl); + } } /** @@ -205,12 +212,13 @@ export abstract class Render { let orientation = Orientation.LANDSCAPE; const blockWidth = this.getBlockWidth(); + const blockHeight = this.getBlockHeight(); const middlePoint: Point = { x: blockWidth / 2, y: this.getBlockHeight() / 2, }; - const ratio = this.setting.width / this.setting.height; + let ratio = this.setting.width / this.setting.height; let pageWidth = this.setting.width; let pageHeight = this.setting.height; @@ -218,26 +226,54 @@ export abstract class Render { let left = middlePoint.x - pageWidth; if (this.setting.size === SizeType.STRETCH) { - if (blockWidth < this.setting.minWidth * 2 && this.app.getSettings().usePortrait) - orientation = Orientation.PORTRAIT; + if(this.app.getSettings().bindingEdge == BindingEdge.TOP_BOTTOM) { + + ratio = this.setting.height / this.setting.width; - pageWidth = - orientation === Orientation.PORTRAIT - ? this.getBlockWidth() - : this.getBlockWidth() / 2; + if (blockHeight< this.setting.minHeight * 2 && this.app.getSettings().usePortrait) + orientation = Orientation.PORTRAIT; - if (pageWidth > this.setting.maxWidth) pageWidth = this.setting.maxWidth; + pageHeight = + orientation === Orientation.PORTRAIT + ? this.getBlockHeight() + : this.getBlockHeight() / 2; - pageHeight = pageWidth / ratio; - if (pageHeight > this.getBlockHeight()) { - pageHeight = this.getBlockHeight(); - pageWidth = pageHeight * ratio; - } + if (pageHeight > this.setting.maxHeight) pageHeight = this.setting.maxHeight; + + pageWidth = pageHeight / ratio; + if (pageWidth > this.getBlockWidth()) { + pageHeight = this.getBlockWidth(); + pageHeight= pageWidth * ratio; + } + + left = + orientation === Orientation.PORTRAIT + ? middlePoint.x - pageHeight / 2 - pageHeight + : middlePoint.x - pageHeight; + + } else { + if (blockWidth < this.setting.minWidth * 2 && this.app.getSettings().usePortrait) + orientation = Orientation.PORTRAIT; + + pageWidth = + orientation === Orientation.PORTRAIT + ? this.getBlockWidth() + : this.getBlockWidth() / 2; - left = - orientation === Orientation.PORTRAIT - ? middlePoint.x - pageWidth / 2 - pageWidth - : middlePoint.x - pageWidth; + if (pageWidth > this.setting.maxWidth) pageWidth = this.setting.maxWidth; + + pageHeight = pageWidth / ratio; + if (pageHeight > this.getBlockHeight()) { + pageHeight = this.getBlockHeight(); + pageWidth = pageHeight * ratio; + } + + left = + orientation === Orientation.PORTRAIT + ? middlePoint.x - pageWidth / 2 - pageWidth + : middlePoint.x - pageWidth; + } + } else { if (blockWidth < pageWidth * 2) { if (this.app.getSettings().usePortrait) { @@ -247,13 +283,25 @@ export abstract class Render { } } - this.boundsRect = { - left, - top: middlePoint.y - pageHeight / 2, - width: pageWidth * 2, - height: pageHeight, - pageWidth: pageWidth, - }; + if(this.app.getSettings().bindingEdge == BindingEdge.TOP_BOTTOM) { + this.boundsRect = { + left: middlePoint.x - pageWidth / 2, + top: middlePoint.y - pageHeight, + width: pageWidth, + height: pageHeight * 2, + pageWidth: pageWidth, + pageHeight: pageHeight + }; + } else { + this.boundsRect = { + left, + top: middlePoint.y - pageHeight / 2, + width: pageWidth * 2, + height: pageHeight, + pageWidth: pageWidth, + pageHeight: pageHeight + }; + } return orientation; } @@ -337,6 +385,13 @@ export abstract class Render { return this.orientation; } + /** + * Get current book rtl direction + */ + public getRTL(): boolean { + return this.rtl; + } + /** * Set page area while flipping * @@ -463,6 +518,8 @@ export abstract class Render { const rect = this.getRect(); + this.getOrientation + const x = direction === FlipDirection.FORWARD ? pos.x + rect.left + rect.width / 2 diff --git a/src/Settings.ts b/src/Settings.ts index d16510d..166006b 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -8,6 +8,16 @@ export const enum SizeType { STRETCH = 'stretch', } +/** + * Binding Edge + */ +export const enum BindingEdge { + /** Binding on the top/bottom axis */ + TOP_BOTTOM = 'TOP_BOTTOM', + /** Binding on the left/right axis */ + LEFT_RIGHT = 'LEFT_RIGHT', +} + /** * Configuration object */ @@ -57,6 +67,10 @@ export interface FlipSetting { /** if this value is true, flipping by clicking on the whole book will be locked. Only on corners */ disableFlipByClick: boolean; + + rtl: boolean; + + bindingEdge: BindingEdge; } export class Settings { @@ -82,6 +96,8 @@ export class Settings { useMouseEvents: true, showPageCorners: true, disableFlipByClick: false, + bindingEdge: BindingEdge.LEFT_RIGHT, + rtl: false }; /** diff --git a/src/Style/stPageFlip.css b/src/Style/stPageFlip.css index 5432da4..0c5e494 100644 --- a/src/Style/stPageFlip.css +++ b/src/Style/stPageFlip.css @@ -58,4 +58,12 @@ position: absolute; left: 0; top: 0; +} + +/* rtl */ +.stf__wrapper.--rtl { + transform: scaleX(-1); +} +.stf__wrapper.--rtl .stf__item > * { + transform: scaleX(-1); } \ No newline at end of file diff --git a/src/UI/UI.ts b/src/UI/UI.ts index fd1629e..5e61322 100644 --- a/src/UI/UI.ts +++ b/src/UI/UI.ts @@ -1,6 +1,6 @@ import { PageFlip } from '../PageFlip'; import { Point } from '../BasicTypes'; -import { FlipSetting, SizeType } from '../Settings'; +import { BindingEdge, FlipSetting, SizeType } from '../Settings'; import { FlipCorner, FlippingState } from '../Flip/Flip'; import { Orientation } from '../Render/Render'; @@ -46,19 +46,29 @@ export abstract class UI { this.app = app; const k = this.app.getSettings().usePortrait ? 1 : 2; - + // Setting block sizes based on configuration - inBlock.style.minWidth = setting.minWidth * k + 'px'; - inBlock.style.minHeight = setting.minHeight + 'px'; - if (setting.size === SizeType.FIXED) { - inBlock.style.minWidth = setting.width * k + 'px'; - inBlock.style.minHeight = setting.height + 'px'; + if(setting.bindingEdge == BindingEdge.TOP_BOTTOM) { + inBlock.style.minWidth = setting.width + 'px'; + inBlock.style.maxWidth = setting.width + 'px'; + inBlock.style.minHeight = setting.height * k + 'px'; + inBlock.style.maxHeight = setting.height * k + 'px'; + } else { + inBlock.style.minWidth = setting.width * k + 'px'; + inBlock.style.minHeight = setting.height + 'px'; + } } if (setting.autoSize) { - inBlock.style.width = '100%'; - inBlock.style.maxWidth = setting.maxWidth * 2 + 'px'; + if(setting.bindingEdge == BindingEdge.TOP_BOTTOM) { + inBlock.style.height = '100%'; + inBlock.style.maxHeight = setting.maxHeight * 2 + 'px'; + inBlock.style.minHeight = '800px'; // Set The Min Height As A Workabkle Number + } else { + inBlock.style.width = '100%'; + inBlock.style.maxWidth = setting.maxWidth * 2 + 'px'; + } } inBlock.style.display = 'block'; @@ -126,6 +136,21 @@ export abstract class UI { this.update(); } + /** + * Updates styles based on book direction + * + * @param {boolean} rtl - New book direction + */ + public setRTLStyle(rtl: boolean): void { + this.wrapper.classList.remove('--rtl'); + + if (rtl) { + this.wrapper.classList.add('--rtl'); + } + + this.update(); + } + protected removeHandlers(): void { window.removeEventListener('resize', this.onResize); @@ -161,7 +186,7 @@ export abstract class UI { const rect = this.distElement.getBoundingClientRect(); return { - x: x - rect.left, + x: this.app.getSettings().rtl ? rect.width - (x - rect.left) : x - rect.left, y: y - rect.top, }; } From cf0bbed6d83f8dca26f531fb7cb5b415172cd25e Mon Sep 17 00:00:00 2001 From: ashley-mixam <69148655+ashley-mixam@users.noreply.github.com> Date: Mon, 8 Jan 2024 09:09:53 +0000 Subject: [PATCH 2/2] MC-4951: Top/Bottom Binding Support --- rollup.config.js | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 rollup.config.js diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index d4d450a..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,24 +0,0 @@ -import typescript from 'rollup-plugin-typescript2'; -import postcss from 'rollup-plugin-postcss'; -import { terser } from 'rollup-plugin-terser'; - -export default [ - { - input: 'src/PageFlip.ts', - output: [{ file: 'dist/js/page-flip.browser.js', format: 'umd', name: 'St' }], - plugins: [ - postcss(), - typescript({ tsconfig: 'tsconfig.json', useTsconfigDeclarationDir: true }), - terser(), - ], - }, - { - input: 'src/PageFlip.ts', - output: [{ file: 'dist/js/page-flip.module.js', format: 'es' }], - plugins: [ - postcss(), - typescript({ tsconfig: 'tsconfig.json', useTsconfigDeclarationDir: true }), - terser(), - ], - }, -];