mirror of
https://github.com/john-okeefe/foliate-js.git
synced 2026-09-30 23:49:10 -04:00
Add double-click zoom toggle to the fx renderer
Desktop counterpart of the existing touch double-tap: at fit scale a double-click zooms to 2.5x at the clicked location; zoomed or panned it resets to 100% centered. Page iframes forward dblclick with converted coordinates and real targets; PDF text-layer spans and annotation links keep native double-click (word selection) in select/text modes. Applies to all fixed-layout content (comics, manga, PDFs, fixed EPUBs).
This commit is contained in:
@@ -145,6 +145,11 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.addEventListener("touchcancel", this.#onTouchCancel.bind(this), {
|
this.addEventListener("touchcancel", this.#onTouchCancel.bind(this), {
|
||||||
passive: false,
|
passive: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Desktop double-click zoom toggle, mirroring the touch double-tap.
|
||||||
|
// Catches events on the host itself (letterbox gutters); page iframes
|
||||||
|
// forward their dblclick separately (see #attachEventListenersToIframe).
|
||||||
|
this.addEventListener("dblclick", this.#handleDoubleClick.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
attributeChangedCallback(name, _, value) {
|
attributeChangedCallback(name, _, value) {
|
||||||
@@ -622,6 +627,34 @@ export class FixedLayout extends HTMLElement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Desktop counterpart of the touch double-tap toggle: at fit scale a
|
||||||
|
// double-click zooms in at the clicked location; zoomed or panned it
|
||||||
|
// resets to 100% centered. PDF text interactions keep native
|
||||||
|
// double-click (word selection, links) in select/text modes — zoom only
|
||||||
|
// when the target isn't text/annotation content. Returns true when the
|
||||||
|
// event was consumed (callers preventDefault then).
|
||||||
|
#handleDoubleClick(event) {
|
||||||
|
if (this.hasAttribute("panel-mode")) return false;
|
||||||
|
if (this.#isPDF && this.#interactionMode !== "pan") {
|
||||||
|
const t = event.realTarget ?? event.target;
|
||||||
|
if (
|
||||||
|
t?.closest?.(".textLayer span") ||
|
||||||
|
t?.closest?.(".annotationLayer a")
|
||||||
|
)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const rect = this.getBoundingClientRect();
|
||||||
|
const cx = event.clientX - rect.left;
|
||||||
|
const cy = event.clientY - rect.top;
|
||||||
|
if (this.#atFitScale()) {
|
||||||
|
this.#zoomByRatio(cx, cy, 2.5);
|
||||||
|
} else {
|
||||||
|
this.resetZoom();
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// ----- touch gestures -----
|
// ----- touch gestures -----
|
||||||
|
|
||||||
#atFitScale() {
|
#atFitScale() {
|
||||||
@@ -1132,6 +1165,27 @@ export class FixedLayout extends HTMLElement {
|
|||||||
this.#handleMouseUp(mouseEvent);
|
this.#handleMouseUp(mouseEvent);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Double-click zoom: forwarded with converted coordinates and the
|
||||||
|
// iframe's real target (for PDF text-layer hit-testing).
|
||||||
|
doc.addEventListener("dblclick", (event) => {
|
||||||
|
const { clientX, clientY } = convertCoords(event);
|
||||||
|
const mouseEvent = new MouseEvent("dblclick", {
|
||||||
|
button: event.button,
|
||||||
|
clientX,
|
||||||
|
clientY,
|
||||||
|
ctrlKey: event.ctrlKey,
|
||||||
|
metaKey: event.metaKey,
|
||||||
|
shiftKey: event.shiftKey,
|
||||||
|
altKey: event.altKey,
|
||||||
|
bubbles: true,
|
||||||
|
cancelable: true,
|
||||||
|
});
|
||||||
|
mouseEvent.sourceIframe = frameId;
|
||||||
|
mouseEvent.sourceFrame = frame;
|
||||||
|
mouseEvent.realTarget = event.target;
|
||||||
|
if (this.#handleDoubleClick(mouseEvent)) event.preventDefault();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#render(side = this.#side) {
|
#render(side = this.#side) {
|
||||||
|
|||||||
Reference in New Issue
Block a user