mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 09:19:56 -05:00
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
import { store } from "@store/state.svelte";
|
|
|
|
let _appliedZoom: number = -1;
|
|
let _vhRafId: number | null = null;
|
|
|
|
export function applyZoom() {
|
|
const uiZoom = store.settings.uiZoom ?? 1.0;
|
|
if (uiZoom === _appliedZoom) return;
|
|
_appliedZoom = uiZoom;
|
|
document.documentElement.style.setProperty("--ui-zoom", String(uiZoom));
|
|
document.documentElement.style.setProperty("--ui-scale", String(uiZoom));
|
|
document.documentElement.style.zoom = `${uiZoom * 100}%`;
|
|
if (_vhRafId !== null) cancelAnimationFrame(_vhRafId);
|
|
_vhRafId = requestAnimationFrame(() => {
|
|
_vhRafId = null;
|
|
document.documentElement.style.setProperty("--visual-vh", `${window.innerHeight / uiZoom}px`);
|
|
});
|
|
}
|
|
|
|
export function handleZoomKey(e: KeyboardEvent) {
|
|
if (!e.ctrlKey) return;
|
|
const current = store.settings.uiZoom ?? 1.0;
|
|
if (e.key === "=" || e.key === "+") { e.preventDefault(); store.settings.uiZoom = Math.min(2.0, Math.round((current + 0.1) * 10) / 10); }
|
|
else if (e.key === "-") { e.preventDefault(); store.settings.uiZoom = Math.max(0.5, Math.round((current - 0.1) * 10) / 10); }
|
|
else if (e.key === "0") { e.preventDefault(); store.settings.uiZoom = 1.0; }
|
|
}
|
|
|
|
export function mountZoomKey(): () => void {
|
|
window.addEventListener("keydown", handleZoomKey);
|
|
return () => window.removeEventListener("keydown", handleZoomKey);
|
|
}
|
|
|
|
export function clampZoom(z: number, min: number, max: number): number {
|
|
return Math.round(Math.min(max, Math.max(min, z)) * 1000) / 1000;
|
|
}
|
|
|
|
export function captureZoomAnchor(
|
|
containerEl: HTMLElement | null,
|
|
style: string,
|
|
out: { el: HTMLElement | null; offset: number },
|
|
) {
|
|
if (!containerEl || style !== "longstrip") return;
|
|
const containerTop = containerEl.getBoundingClientRect().top;
|
|
for (const img of containerEl.querySelectorAll<HTMLElement>("img[data-local-page]")) {
|
|
const rect = img.getBoundingClientRect();
|
|
if (rect.bottom > containerTop) { out.el = img; out.offset = rect.top - containerTop; return; }
|
|
}
|
|
}
|
|
|
|
export function restoreZoomAnchor(
|
|
containerEl: HTMLElement | null,
|
|
out: { el: HTMLElement | null; offset: number },
|
|
) {
|
|
if (!out.el || !containerEl) return;
|
|
const el = out.el;
|
|
out.el = null;
|
|
requestAnimationFrame(() => {
|
|
const containerTop = containerEl!.getBoundingClientRect().top;
|
|
containerEl!.scrollTop += (el.getBoundingClientRect().top - containerTop) - out.offset;
|
|
});
|
|
} |