ofd-reader
v0.1.3
Published
A lightweight browser OFD reader component with SVG rendering.
Maintainers
Readme
OFD Reader
轻量、框架无关的 Web OFD 阅读组件。当前项目处于 0.x 预览开发阶段,重点是稳定基础阅读能力和 TypeScript API。
功能状态
- OFD ZIP/XML 解析。
- SVG 页面渲染。
- 本地 OFD 文件加载。
- 缩放、适宽、适页。
- 页码跳转和当前页事件。
- 缩略图导航。
- loading、empty、error 状态。
- 基础
Clips裁剪支持。
搜索高亮、文本选择、签章展示和验签仍在规划中。
安装
npm install ofd-reader当前 0.x 为预览版,适合先在真实业务环境中验证基础浏览、缩放、页码跳转和缩略图能力。
许可证
本项目使用 AGPL-3.0-or-later 许可证。
AGPL 允许商业使用,但如果将本项目或其修改版本用于网络服务、Web 系统或分发场景,需要按照 AGPL 要求向用户提供对应源码。若需要闭源商业授权,请联系维护者另行授权。
基础使用
import { createOFDViewer } from 'ofd-reader'
import 'ofd-reader/style.css'
const container = document.getElementById('app')
if (!container) {
throw new Error('Container not found')
}
const viewer = createOFDViewer(container, {
defaultScale: 'fit-width',
maxFitWidth: 980,
thumbnails: {
enabled: true,
width: 110
}
})
await viewer.load(file)load() 接收浏览器 File、Blob 或 ArrayBuffer。如果你需要从远程地址加载,可以先自行 fetch:
const response = await fetch('/demo.ofd')
const blob = await response.blob()
await viewer.load(blob)自定义工具栏
组件不内置键盘快捷键。业务侧可以通过 API 绑定按钮或快捷键:
zoomInButton.onclick = () => viewer.zoomIn()
zoomOutButton.onclick = () => viewer.zoomOut()
fitWidthButton.onclick = () => viewer.fitWidth()
fitPageButton.onclick = () => viewer.fitPage()
window.addEventListener('keydown', event => {
if (event.ctrlKey && event.key === '=') {
event.preventDefault()
viewer.zoomIn()
}
})配置项
interface OFDViewerOptions {
defaultScale?: number | 'fit-width' | 'fit-page'
minScale?: number
maxScale?: number
scaleStep?: number
maxFitWidth?: number
thumbnails?: boolean | {
enabled?: boolean
width?: number
}
stateMessages?: OFDViewerStateMessages
className?: string
}defaultScale:初始缩放比例,或使用适宽/适页模式。minScale/maxScale:缩放上下限,默认0.25到4。scaleStep:zoomIn()/zoomOut()的步进,默认0.1。maxFitWidth:限制fit-width在大屏下的最大阅读宽度。thumbnails:是否启用缩略图,或配置缩略图宽度。stateMessages:自定义 empty/loading/error 文案。className:附加到 viewer 根节点的 class。
事件监听
viewer.on('pagechange', ({ pageIndex, previousPageIndex, pageCount }) => {
console.log(pageIndex + 1, previousPageIndex + 1, pageCount)
})
viewer.on('scalechange', ({ scale, previousScale, mode }) => {
console.log(scale, previousScale, mode)
})
viewer.on('statuschange', ({ status, previousStatus, error }) => {
console.log(status, previousStatus, error)
})事件 payload:
interface OFDViewerEventMap {
load: {
package: OFDPackage
pageCount: number
}
error: {
error: unknown
}
scalechange: {
scale: number
previousScale: number
mode: 'fit-width' | 'fit-page' | null
}
pagechange: {
pageIndex: number
previousPageIndex: number
pageCount: number
}
statuschange: {
status: 'empty' | 'loading' | 'ready' | 'error'
previousStatus: 'empty' | 'loading' | 'ready' | 'error'
error?: unknown
}
}公开 API
parse(file: ArrayBuffer | Blob): Promise<OFDPackage>
render(pkg: OFDPackage, container: HTMLElement, options?: RenderOptions): Promise<void>
createOFDViewer(container: HTMLElement, options?: OFDViewerOptions): OFDViewer普通业务集成优先使用 createOFDViewer。parse 和 render 更适合调试、二次封装或高级场景。
OFDPackage 中的 zip 字段被视为内部资源,公开类型中不会绑定到具体 ZIP 实现。
低层 API 示例:
import { parse, render } from 'ofd-reader'
const pkg = await parse(file)
await render(pkg, container)Viewer 方法
load(file)clear()destroy()setScale(scale)zoomIn()zoomOut()fitWidth()fitPage()goToPage(pageIndex)previousPage()nextPage()showThumbnails()hideThumbnails()toggleThumbnails(force?)getScale()getScaleMode()getCurrentPage()getPageCount()getPackage()getStatus()on(event, handler)off(event, handler)
样式
阅读器默认样式需要单独引入:
import 'ofd-reader/style.css'组件不依赖任何 UI 框架,外层容器的宽高由业务页面控制。viewer 会在传入容器内部创建自己的阅读区域和缩略图区域。
浏览器兼容
当前实现面向现代浏览器,同时对 Chrome 69+ 做了基础兼容处理。主要依赖:
BlobURL.createObjectURLFontFaceResizeObserverIntersectionObserver- SVG 渲染能力
推荐运行环境:
- Chrome / Edge 90+
- Firefox 90+
- Safari 15+
基础兼容目标:
- Chrome 69+
Chrome 69+ 可用于基础阅读、缩放、适宽/适页、页码跳转和缩略图导航。由于老版本浏览器在 CSS、字体和滚动行为上仍可能存在细节差异,发布前建议在目标 WebView 或浏览器中做一次视觉回归检查。
如果目标环境缺少 ResizeObserver 或 IntersectionObserver,基础页面渲染仍可工作,但适宽/适页重算、缩略图懒加载等体验可能降级。组件目前不提供内置 polyfill,业务项目可按目标浏览器自行引入。
已知限制
- 暂无正式单元测试。
- 搜索、高亮、文本选择尚未实现。
CompositeObject、复杂颜色管理、PatternReflect等长尾能力尚未完整支持。- 签章展示、签名解析和验签属于后期增强能力。
