mirror of
https://github.com/xiaoqidun/ofdgo.git
synced 2026-10-30 01:27:26 +08:00
1 parent
e60ad5d6c2
commit
abbd4de13a
3 files changed
+72
No files matched your search
@@ -37,6 +37,7 @@
|
|||||||
<button id="fitButton" class="button" type="button" data-short="宽" aria-label="适宽" disabled>适宽</button>
|
<button id="fitButton" class="button" type="button" data-short="宽" aria-label="适宽" disabled>适宽</button>
|
||||||
<button id="fitHeightButton" class="button" type="button" data-short="高" aria-label="适高" disabled>适高</button>
|
<button id="fitHeightButton" class="button" type="button" data-short="高" aria-label="适高" disabled>适高</button>
|
||||||
<button id="rotateButton" class="button" type="button" data-short="转" title="顺时针旋转90°" aria-label="旋转" disabled>旋转</button>
|
<button id="rotateButton" class="button" type="button" data-short="转" title="顺时针旋转90°" aria-label="旋转" disabled>旋转</button>
|
||||||
|
<button id="panButton" class="button" type="button" data-short="拖" title="拖动页面" aria-label="拖动" aria-pressed="false" disabled>拖动</button>
|
||||||
<button id="continuousButton" class="button" type="button" data-short="连" title="无距连续显示" aria-label="无距连续显示" aria-pressed="false" disabled>连续</button>
|
<button id="continuousButton" class="button" type="button" data-short="连" title="无距连续显示" aria-label="无距连续显示" aria-pressed="false" disabled>连续</button>
|
||||||
<button id="annotationButton" class="button" type="button" data-short="注" title="关闭注解" aria-label="关闭注解" aria-pressed="true">注解</button>
|
<button id="annotationButton" class="button" type="button" data-short="注" title="关闭注解" aria-label="关闭注解" aria-pressed="true">注解</button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -659,6 +659,19 @@ button.outline-link:hover {
|
|||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.viewer-panel.pan-mode,
|
||||||
|
.pan-mode .text-run > span {
|
||||||
|
cursor: grab;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewer-panel.panning,
|
||||||
|
.panning .text-layer,
|
||||||
|
.panning .text-run > span {
|
||||||
|
cursor: grabbing;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
inset: 0;
|
inset: 0;
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ const state = {
|
|||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
rotation: 0,
|
rotation: 0,
|
||||||
|
panMode: false,
|
||||||
|
pan: null,
|
||||||
fitMode: "width",
|
fitMode: "width",
|
||||||
continuous: false,
|
continuous: false,
|
||||||
renderAnnotations: true,
|
renderAnnotations: true,
|
||||||
@@ -86,6 +88,7 @@ const el = {
|
|||||||
fitButton: document.querySelector("#fitButton"),
|
fitButton: document.querySelector("#fitButton"),
|
||||||
fitHeightButton: document.querySelector("#fitHeightButton"),
|
fitHeightButton: document.querySelector("#fitHeightButton"),
|
||||||
rotateButton: document.querySelector("#rotateButton"),
|
rotateButton: document.querySelector("#rotateButton"),
|
||||||
|
panButton: document.querySelector("#panButton"),
|
||||||
continuousButton: document.querySelector("#continuousButton"),
|
continuousButton: document.querySelector("#continuousButton"),
|
||||||
annotationButton: document.querySelector("#annotationButton"),
|
annotationButton: document.querySelector("#annotationButton"),
|
||||||
imageDPI: document.querySelector("#imageDPI"),
|
imageDPI: document.querySelector("#imageDPI"),
|
||||||
@@ -196,6 +199,7 @@ el.zoomInButton.addEventListener("click", () => setScale(state.scale + 0.1));
|
|||||||
el.fitButton.addEventListener("click", fitWidth);
|
el.fitButton.addEventListener("click", fitWidth);
|
||||||
el.fitHeightButton.addEventListener("click", fitHeight);
|
el.fitHeightButton.addEventListener("click", fitHeight);
|
||||||
el.rotateButton.addEventListener("click", rotatePages);
|
el.rotateButton.addEventListener("click", rotatePages);
|
||||||
|
el.panButton.addEventListener("click", togglePan);
|
||||||
el.continuousButton.addEventListener("click", toggleContinuous);
|
el.continuousButton.addEventListener("click", toggleContinuous);
|
||||||
el.annotationButton.addEventListener("click", toggleAnnotations);
|
el.annotationButton.addEventListener("click", toggleAnnotations);
|
||||||
document.addEventListener("copy", copySelection);
|
document.addEventListener("copy", copySelection);
|
||||||
@@ -215,10 +219,16 @@ el.pageInput.addEventListener("change", () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
window.addEventListener("resize", resizeViewer);
|
window.addEventListener("resize", resizeViewer);
|
||||||
|
window.addEventListener("blur", () => endPan());
|
||||||
COMPACT_LAYOUT.addEventListener("change", syncLayoutMode);
|
COMPACT_LAYOUT.addEventListener("change", syncLayoutMode);
|
||||||
el.viewerPanel.addEventListener("scroll", () => {
|
el.viewerPanel.addEventListener("scroll", () => {
|
||||||
schedulePageSync();
|
schedulePageSync();
|
||||||
});
|
});
|
||||||
|
el.viewerPanel.addEventListener("pointerdown", startPan);
|
||||||
|
el.viewerPanel.addEventListener("pointermove", movePan);
|
||||||
|
el.viewerPanel.addEventListener("pointerup", endPan);
|
||||||
|
el.viewerPanel.addEventListener("pointercancel", endPan);
|
||||||
|
el.viewerPanel.addEventListener("lostpointercapture", endPan);
|
||||||
el.viewerPanel.addEventListener("click", () => {
|
el.viewerPanel.addEventListener("click", () => {
|
||||||
if (COMPACT_LAYOUT.matches && (state.showPages || state.showMeta)) {
|
if (COMPACT_LAYOUT.matches && (state.showPages || state.showMeta)) {
|
||||||
state.showPages = false;
|
state.showPages = false;
|
||||||
@@ -2838,6 +2848,52 @@ function pageViewSize(page) {
|
|||||||
return state.rotation % 180 ? { width: page.height, height: page.width } : page;
|
return state.rotation % 180 ? { width: page.height, height: page.width } : page;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function togglePan() {
|
||||||
|
if (document.body.hasAttribute("aria-busy")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
endPan();
|
||||||
|
state.panMode = !state.panMode;
|
||||||
|
el.viewerPanel.classList.toggle("pan-mode", state.panMode);
|
||||||
|
el.panButton.setAttribute("aria-pressed", String(state.panMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
function startPan(event) {
|
||||||
|
if (!state.panMode || !state.doc || event.pointerType !== "mouse" || event.button !== 0 || document.body.hasAttribute("aria-busy") || event.target.closest("a")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const rect = el.viewerPanel.getBoundingClientRect();
|
||||||
|
if (event.clientX >= rect.left + el.viewerPanel.clientWidth || event.clientY >= rect.top + el.viewerPanel.clientHeight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
event.preventDefault();
|
||||||
|
state.pan = { id: event.pointerId, x: event.clientX + el.viewerPanel.scrollLeft, y: event.clientY + el.viewerPanel.scrollTop };
|
||||||
|
el.viewerPanel.setPointerCapture(event.pointerId);
|
||||||
|
el.viewerPanel.classList.add("panning");
|
||||||
|
el.viewerPanel.focus({ preventScroll: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
function movePan(event) {
|
||||||
|
const pan = state.pan;
|
||||||
|
if (!pan || event.pointerId !== pan.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
el.viewerPanel.scrollLeft = pan.x - event.clientX;
|
||||||
|
el.viewerPanel.scrollTop = pan.y - event.clientY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function endPan(event) {
|
||||||
|
const pan = state.pan;
|
||||||
|
if (!pan || (event && event.pointerId !== pan.id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
state.pan = null;
|
||||||
|
el.viewerPanel.classList.remove("panning");
|
||||||
|
if (el.viewerPanel.hasPointerCapture(pan.id)) {
|
||||||
|
el.viewerPanel.releasePointerCapture(pan.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function fitWidth(updateStatus = true) {
|
function fitWidth(updateStatus = true) {
|
||||||
const page = currentPageInfo();
|
const page = currentPageInfo();
|
||||||
if (!page) {
|
if (!page) {
|
||||||
@@ -3026,6 +3082,7 @@ function updateControls() {
|
|||||||
el.fitButton.disabled = !hasDoc;
|
el.fitButton.disabled = !hasDoc;
|
||||||
el.fitHeightButton.disabled = !hasDoc;
|
el.fitHeightButton.disabled = !hasDoc;
|
||||||
el.rotateButton.disabled = !hasDoc;
|
el.rotateButton.disabled = !hasDoc;
|
||||||
|
el.panButton.disabled = !hasDoc;
|
||||||
el.continuousButton.disabled = !hasDoc;
|
el.continuousButton.disabled = !hasDoc;
|
||||||
el.fitButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "width");
|
el.fitButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "width");
|
||||||
el.fitHeightButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "height");
|
el.fitHeightButton.toggleAttribute("aria-pressed", hasDoc && state.fitMode === "height");
|
||||||
@@ -3080,6 +3137,7 @@ function setBusy(busy, text = "", percent = 0, status = "") {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
endPan();
|
||||||
el.progressPanel.hidden = false;
|
el.progressPanel.hidden = false;
|
||||||
setProgress(text, percent, status);
|
setProgress(text, percent, status);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user