feat(前端界面): 优化DPI支持
build.yaml / build (push) Successful in 33s

This commit is contained in:
2026-07-09 16:46:48 +08:00
parent ba1da58992
commit 48aabc77ab
4 changed files with 46 additions and 38 deletions
+4 -4
View File
@@ -33,15 +33,15 @@
<button id="fitButton" class="button" type="button" data-short="宽" disabled>适宽</button>
<button id="fitHeightButton" class="button" type="button" data-short="高" disabled>适高</button>
<button id="annotationButton" class="button" type="button" data-short="注" title="渲染注解" aria-label="渲染注解" aria-pressed="true">注解</button>
<select id="renderDPI" class="format-select dpi-select" title="渲染 DPI" aria-label="渲染 DPI">
</div>
<div class="tool-group">
<select id="pageExportFormat" class="format-select" title="单页格式" aria-label="单页格式" disabled></select>
<select id="imageDPI" class="format-select dpi-select" title="图片 DPI" aria-label="图片 DPI" disabled>
<option value="96">96</option>
<option value="150">150</option>
<option value="300" selected>300</option>
<option value="600">600</option>
</select>
</div>
<div class="tool-group">
<select id="pageExportFormat" class="format-select" title="单页格式" aria-label="单页格式" disabled></select>
<button id="exportPageButton" class="button" type="button" data-short="单" title="导出单页" aria-label="导出单页" disabled>单页</button>
<button id="exportButton" class="button" type="button" data-short="全" title="导出文档 PDF" aria-label="导出文档 PDF" disabled>文档</button>
</div>
+19 -21
View File
@@ -18,7 +18,7 @@ const COMMON_FONT_NAMES = [
];
const LOCAL_FONT_LOAD_LIMIT = 16;
const COMPACT_LAYOUT = window.matchMedia("(max-width: 900px)");
const DEFAULT_RENDER_DPI = 300;
const DEFAULT_IMAGE_DPI = 300;
const STATUS = {
ready: "选择 OFD 文件",
opening: "正在打开 OFD",
@@ -60,7 +60,6 @@ const state = {
pageIndex: 0,
scale: 1,
fitMode: "width",
renderDPI: DEFAULT_RENDER_DPI,
renderAnnotations: true,
pageCache: new Map(),
pageInFlight: new Map(),
@@ -94,7 +93,7 @@ const el = {
fitButton: document.querySelector("#fitButton"),
fitHeightButton: document.querySelector("#fitHeightButton"),
annotationButton: document.querySelector("#annotationButton"),
renderDPI: document.querySelector("#renderDPI"),
imageDPI: document.querySelector("#imageDPI"),
pageExportFormat: document.querySelector("#pageExportFormat"),
exportPageButton: document.querySelector("#exportPageButton"),
exportButton: document.querySelector("#exportButton"),
@@ -139,7 +138,7 @@ el.zoomInButton.addEventListener("click", () => setScale(state.scale + 0.1));
el.fitButton.addEventListener("click", fitWidth);
el.fitHeightButton.addEventListener("click", fitHeight);
el.annotationButton.addEventListener("click", toggleAnnotations);
el.renderDPI.addEventListener("change", changeDPI);
el.pageExportFormat.addEventListener("change", () => updateDPIControl());
el.exportPageButton.addEventListener("click", exportCurrentPage);
el.exportButton.addEventListener("click", exportPDF);
el.pageInput.addEventListener("change", () => {
@@ -246,6 +245,7 @@ function loadExportFormats() {
if (formats.length) {
el.pageExportFormat.value = formats[0].value;
}
updateDPIControl();
}
async function ensureWASM() {
@@ -740,19 +740,6 @@ async function toggleAnnotations() {
});
}
async function changeDPI() {
state.renderDPI = currentRenderDPI();
if (!state.ofdBytes || !state.doc) {
return;
}
await openDocument({
pageIndex: state.pageIndex,
fitMode: state.fitMode,
scale: state.scale,
skipAutoFonts: true,
});
}
function removeFont(id) {
state.localFonts = state.localFonts.filter((font) => font.id !== id);
state.userFonts = state.userFonts.filter((font) => font.id !== id);
@@ -896,7 +883,7 @@ async function openDocument(options = {}) {
if (openSeq !== state.openSeq) {
return;
}
const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations, state.renderDPI);
const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations);
if (openSeq !== state.openSeq) {
return;
}
@@ -1054,7 +1041,8 @@ async function exportCurrentPage() {
if (openSeq !== state.openSeq) {
return;
}
const result = callWASM("ofdgoExportPage", state.pageIndex, format);
const dpi = exportFormatUsesDPI(format) ? currentImageDPI() : 0;
const result = callWASM("ofdgoExportPage", state.pageIndex, format, dpi);
if (openSeq !== state.openSeq) {
return;
}
@@ -2130,6 +2118,7 @@ function updateControls() {
el.pageExportFormat.disabled = !hasDoc || !state.exportFormats.length;
el.exportPageButton.disabled = !hasDoc || !state.exportFormats.length;
el.exportButton.disabled = !hasDoc;
updateDPIControl();
}
function updateAnnotationButton() {
@@ -2142,6 +2131,7 @@ function setExportControlsDisabled(disabled) {
el.exportButton.disabled = disabled;
el.exportPageButton.disabled = disabled;
el.pageExportFormat.disabled = disabled;
updateDPIControl(disabled);
}
function callWASM(name, ...args) {
@@ -2259,8 +2249,16 @@ function exportFormatInfo(value) {
return state.exportFormats.find((format) => format.value === value) || null;
}
function currentRenderDPI() {
return Number.parseFloat(el.renderDPI.value) || DEFAULT_RENDER_DPI;
function exportFormatUsesDPI(value) {
return value === "png" || value === "jpg";
}
function updateDPIControl(disabled = false) {
el.imageDPI.disabled = disabled || !state.doc || !exportFormatUsesDPI(el.pageExportFormat.value);
}
function currentImageDPI() {
return Number.parseFloat(el.imageDPI.value) || DEFAULT_IMAGE_DPI;
}
function formatBytes(size, fallback = "PDF") {