mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-09 11:29:14 -04:00
Center on focused frame instead of full spread when zoomed in
When a numeric zoom is active and both panes have content, #render() now centers on the frame indicated by #side rather than centering the entire spread. This means on page turns the view starts on the correct frame (left for LTR, right for RTL) instead of the middle of the spread. For fit-page/fit-width and single-pane views, centering behavior is unchanged.
This commit is contained in:
+54
-6
@@ -204,9 +204,12 @@ export class FixedLayout extends HTMLElement {
|
|||||||
#updateFrameScales(scale) {
|
#updateFrameScales(scale) {
|
||||||
const left = this.#left ?? {};
|
const left = this.#left ?? {};
|
||||||
const right = this.#center ?? this.#right ?? {};
|
const right = this.#center ?? this.#right ?? {};
|
||||||
const { width: hostWidth, height: hostHeight } = this.getBoundingClientRect();
|
const { width: hostWidth, height: hostHeight } =
|
||||||
|
this.getBoundingClientRect();
|
||||||
const portrait =
|
const portrait =
|
||||||
this.spread !== "both" && this.spread !== "portrait" && hostHeight > hostWidth;
|
this.spread !== "both" &&
|
||||||
|
this.spread !== "portrait" &&
|
||||||
|
hostHeight > hostWidth;
|
||||||
const target = this.#side === "left" ? left : right;
|
const target = this.#side === "left" ? left : right;
|
||||||
const blankWidth = left.width ?? right.width ?? 0;
|
const blankWidth = left.width ?? right.width ?? 0;
|
||||||
const blankHeight = left.height ?? right.height ?? 0;
|
const blankHeight = left.height ?? right.height ?? 0;
|
||||||
@@ -245,9 +248,12 @@ export class FixedLayout extends HTMLElement {
|
|||||||
#getContentSize() {
|
#getContentSize() {
|
||||||
const left = this.#left ?? {};
|
const left = this.#left ?? {};
|
||||||
const right = this.#center ?? this.#right ?? {};
|
const right = this.#center ?? this.#right ?? {};
|
||||||
const { width: hostWidth, height: hostHeight } = this.getBoundingClientRect();
|
const { width: hostWidth, height: hostHeight } =
|
||||||
|
this.getBoundingClientRect();
|
||||||
const portrait =
|
const portrait =
|
||||||
this.spread !== "both" && this.spread !== "portrait" && hostHeight > hostWidth;
|
this.spread !== "both" &&
|
||||||
|
this.spread !== "portrait" &&
|
||||||
|
hostHeight > hostWidth;
|
||||||
const target = this.#side === "left" ? left : right;
|
const target = this.#side === "left" ? left : right;
|
||||||
const blankWidth = left.width ?? right.width ?? 0;
|
const blankWidth = left.width ?? right.width ?? 0;
|
||||||
const blankHeight = left.height ?? right.height ?? 0;
|
const blankHeight = left.height ?? right.height ?? 0;
|
||||||
@@ -334,6 +340,14 @@ export class FixedLayout extends HTMLElement {
|
|||||||
if (!this.#dragState.isDragging) return;
|
if (!this.#dragState.isDragging) return;
|
||||||
this.#dragState.isDragging = false;
|
this.#dragState.isDragging = false;
|
||||||
this.style.cursor = "";
|
this.style.cursor = "";
|
||||||
|
|
||||||
|
// sync #side with the frame the user actually panned to
|
||||||
|
if (!this.#center && !this.#left?.blank && !this.#right?.blank) {
|
||||||
|
const leftWidth = (this.#left.width ?? 0) * this.#transform.scale;
|
||||||
|
const viewportCenterInWrapper =
|
||||||
|
this.getBoundingClientRect().width / 2 - this.#transform.x;
|
||||||
|
this.#side = viewportCenterInWrapper < leftWidth ? "left" : "right";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async #createFrame({ index, src: srcOption }, frameId) {
|
async #createFrame({ index, src: srcOption }, frameId) {
|
||||||
@@ -386,7 +400,8 @@ export class FixedLayout extends HTMLElement {
|
|||||||
const iframeRect = frame.iframe.getBoundingClientRect();
|
const iframeRect = frame.iframe.getBoundingClientRect();
|
||||||
const flRect = this.getBoundingClientRect();
|
const flRect = this.getBoundingClientRect();
|
||||||
const scaleX = iframeRect.width / (doc.documentElement.clientWidth || 1);
|
const scaleX = iframeRect.width / (doc.documentElement.clientWidth || 1);
|
||||||
const scaleY = iframeRect.height / (doc.documentElement.clientHeight || 1);
|
const scaleY =
|
||||||
|
iframeRect.height / (doc.documentElement.clientHeight || 1);
|
||||||
return {
|
return {
|
||||||
clientX: iframeRect.left - flRect.left + e.clientX * scaleX,
|
clientX: iframeRect.left - flRect.left + e.clientX * scaleX,
|
||||||
clientY: iframeRect.top - flRect.top + e.clientY * scaleY,
|
clientY: iframeRect.top - flRect.top + e.clientY * scaleY,
|
||||||
@@ -527,9 +542,24 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.#updateFrameScales(scale);
|
this.#updateFrameScales(scale);
|
||||||
|
|
||||||
const { contentWidth, contentHeight } = this.#getContentSize();
|
const { contentWidth, contentHeight } = this.#getContentSize();
|
||||||
this.#transform.x = (width - contentWidth) / 2;
|
|
||||||
this.#transform.y = (height - contentHeight) / 2;
|
this.#transform.y = (height - contentHeight) / 2;
|
||||||
|
|
||||||
|
const isNumericZoom = typeof this.#zoom === "number" && !isNaN(this.#zoom);
|
||||||
|
const hasDualFrames =
|
||||||
|
!this.#center && !this.#left?.blank && !this.#right?.blank;
|
||||||
|
|
||||||
|
if (isNumericZoom && hasDualFrames) {
|
||||||
|
const leftWidth = (this.#left.width ?? 0) * scale;
|
||||||
|
const rightWidth = (this.#right.width ?? 0) * scale;
|
||||||
|
if (side === "right") {
|
||||||
|
this.#transform.x = (width - rightWidth) / 2 - leftWidth;
|
||||||
|
} else {
|
||||||
|
this.#transform.x = (width - leftWidth) / 2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.#transform.x = (width - contentWidth) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
this.#applyTransform();
|
this.#applyTransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,6 +592,15 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.#reportLocation("page");
|
this.#reportLocation("page");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zoomed-in dual-pane - pan to left frame
|
||||||
|
if (typeof this.#zoom === "number" && !this.#right?.blank) {
|
||||||
|
if (this.#side === "right") {
|
||||||
|
this.#side = "left";
|
||||||
|
this.#render();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#goRight() {
|
#goRight() {
|
||||||
@@ -572,6 +611,15 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.#reportLocation("page");
|
this.#reportLocation("page");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// zoomed-in dual-pane - pan to right frame
|
||||||
|
if (typeof this.#zoom === "number" && !this.#left?.blank) {
|
||||||
|
if (this.#side === "left") {
|
||||||
|
this.#side = "right";
|
||||||
|
this.#render();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open(book) {
|
open(book) {
|
||||||
|
|||||||
Reference in New Issue
Block a user