From 89577ea72f90a69344798b4f8c6424d8354c10a9 Mon Sep 17 00:00:00 2001 From: xiaoqidun Date: Thu, 9 Jul 2026 14:10:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=89=8D=E7=AB=AF=E7=95=8C=E9=9D=A2):=20O?= =?UTF-8?q?FDGo=20WebUI=E6=94=AF=E6=8C=81=E8=AE=BE=E7=BD=AEDPI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/webui/index.html | 6 ++++++ assets/webui/ofdgo.css | 8 ++++++++ assets/webui/ofdgo.js | 25 +++++++++++++++++++++++-- internal/webui/wasm.go | 5 +++-- internal/webui/webui.go | 4 ++++ 5 files changed, 44 insertions(+), 4 deletions(-) diff --git a/assets/webui/index.html b/assets/webui/index.html index 89c18d0..77ee46d 100644 --- a/assets/webui/index.html +++ b/assets/webui/index.html @@ -33,6 +33,12 @@ +
diff --git a/assets/webui/ofdgo.css b/assets/webui/ofdgo.css index 0da9bdc..9a3ee4f 100644 --- a/assets/webui/ofdgo.css +++ b/assets/webui/ofdgo.css @@ -217,6 +217,10 @@ button:not(:disabled):hover { color: #1f2428; } +.dpi-select { + width: 54px; +} + .format-select:focus, .format-select:focus-visible { border-color: var(--accent); @@ -1078,6 +1082,10 @@ body[data-hide-meta] .meta-panel { padding: 0 3px; } + .dpi-select { + width: 48px; + } + .footer-links { justify-content: flex-end; } diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js index 9e53382..89ee969 100644 --- a/assets/webui/ofdgo.js +++ b/assets/webui/ofdgo.js @@ -18,6 +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 STATUS = { ready: "选择 OFD 文件", opening: "正在打开 OFD", @@ -59,6 +60,7 @@ const state = { pageIndex: 0, scale: 1, fitMode: "width", + renderDPI: DEFAULT_RENDER_DPI, renderAnnotations: true, pageCache: new Map(), pageInFlight: new Map(), @@ -92,6 +94,7 @@ const el = { fitButton: document.querySelector("#fitButton"), fitHeightButton: document.querySelector("#fitHeightButton"), annotationButton: document.querySelector("#annotationButton"), + renderDPI: document.querySelector("#renderDPI"), pageExportFormat: document.querySelector("#pageExportFormat"), exportPageButton: document.querySelector("#exportPageButton"), exportButton: document.querySelector("#exportButton"), @@ -136,6 +139,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.exportPageButton.addEventListener("click", exportCurrentPage); el.exportButton.addEventListener("click", exportPDF); el.pageInput.addEventListener("change", () => { @@ -730,6 +734,19 @@ 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); @@ -873,7 +890,7 @@ async function openDocument(options = {}) { if (openSeq !== state.openSeq) { return; } - const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations); + const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations, state.renderDPI); if (openSeq !== state.openSeq) { return; } @@ -881,7 +898,7 @@ async function openDocument(options = {}) { const pageIndex = Math.min(Math.max(options.pageIndex || 0, 0), Math.max(pageCount - 1, 0)); state.doc = doc; state.pageIndex = pageIndex; - state.scale = 1; + state.scale = options.scale || 1; state.fitMode = options.fitMode || "width"; if (!options.skipAutoFonts && await autoLoadDocumentLocalFonts(openSeq)) { if (openSeq !== state.openSeq) { @@ -2183,6 +2200,10 @@ function exportFormatInfo(value) { return state.exportFormats.find((format) => format.value === value) || null; } +function currentRenderDPI() { + return Number.parseFloat(el.renderDPI.value) || DEFAULT_RENDER_DPI; +} + function formatBytes(size, fallback = "PDF") { if (!Number.isFinite(size) || size <= 0) { return fallback; diff --git a/internal/webui/wasm.go b/internal/webui/wasm.go index 7e54337..ac733be 100644 --- a/internal/webui/wasm.go +++ b/internal/webui/wasm.go @@ -79,7 +79,7 @@ func safeCall(fn func([]js.Value) (any, error), args []js.Value) (data any, err // 入参: args 浏览器参数 // 返回: any 文档信息, error 错误信息 func openDocument(args []js.Value) (any, error) { - if len(args) < 3 { + if len(args) < 4 { return nil, fmt.Errorf("missing open arguments") } data, err := bytesFromJS(args[0]) @@ -91,11 +91,12 @@ func openDocument(args []js.Value) (any, error) { return nil, err } renderAnnotations := args[2].Bool() + dpi := args[3].Float() if currentSession != nil { _ = currentSession.Close() currentSession = nil } - session, err := Open(data, OpenOptions{Fonts: fonts, RenderAnnotations: renderAnnotations}) + session, err := Open(data, OpenOptions{Fonts: fonts, DPI: dpi, RenderAnnotations: renderAnnotations}) if err != nil { return nil, err } diff --git a/internal/webui/webui.go b/internal/webui/webui.go index 9919516..bed492c 100644 --- a/internal/webui/webui.go +++ b/internal/webui/webui.go @@ -30,6 +30,7 @@ import ( // OpenOptions 打开OFD文档选项 type OpenOptions struct { Fonts []FontFile + DPI float64 RenderAnnotations bool } @@ -186,6 +187,9 @@ func Open(data []byte, opts OpenOptions) (*Session, error) { return nil, err } var rendererOptions []ofdgo.RendererOption + if opts.DPI > 0 { + rendererOptions = append(rendererOptions, ofdgo.WithDPI(opts.DPI)) + } if len(opts.Fonts) > 0 { fontFS := ofdgo.NewFontFS(opts.Fonts) if fontFS.Len() == 0 {