流光年华|VUE 实现高性能的 PDF 在线预览( 二 )


注意在 PDF 文档中存在有中文时 , 会出现不显示的情况 , 控制台也会报如下的错误提示
Warning: The CMap "baseUrl" parameter must be specified, ensure that the "cMapUrl" and "cMapPacked" API parameters are provided.【流光年华|VUE 实现高性能的 PDF 在线预览】主要是 PDF 文档内容存在不支持的字体 , 暂且引入三方字体来解决该问题
const url = `${md5}-${page}.pdf?id=${fid}const promise = PDFJS.getDocument({url,cMapUrl,cMapPacked: true}).promise;渲染 PDF 文档因为我实现的是 PDF 一页的内容 , 按屏幕尺寸 100% 宽度来显示的 , 这样很容易高度就超出可视范围了 , 所以单页采用滚动形式 , 多页则采用按钮触发翻页的形式来展示(为了更好的适配不同尺寸的屏幕 , 显示的效果与主讲人完全同步) , 并非采用一字往下无限排 , 滚动翻页的形式 。
/** * 获取分片 * @param fid 文件ID * @param md5 文件唯一标识 * @param token 授权码 * @param num 第N个分片 */public getFragmentation( fid: number, md5: string, token: string, num = 0) { // 请求分片, 得到 promise... // ... promise.then((pdf: any) => {for (let i = 1; i <= pdf.numPages; i++) {pdf.getPage(i).then((page) => {const pagination = num * 5 + i;this.renderPage(pagination, page);});} });}/** * 渲染分页内容. * @param pagination 第N页 * @param page 分页属性 */protected renderPage( pagination: number, page: any) { // 根据缩放比例, 获取文档的可视属性 const viewport = page.getViewport({scale: 1}); // 创建用于渲染的Canvas元素 const canvas = document.createElement('canvas'),context = canvas.getContext('2d');canvas.width = viewport.width;canvas.height = viewport.height; // 渲染文档 const renderContext = {canvasContext: context,viewport }; return page.render(renderContext).promise;}PDF 文档翻页在上一页/下一页的不断操作中 , 1000页的内容 , 不断的进行渲染 , 难不成要渲染1000个DOM出来?显然不合理 , 非得把浏览器给搞崩了才肯罢休吗?几十个 Canvas 就让你卡的不要不要的了 。 具体实现也简单 , 保证只显示 5 个的前提下 , 根据上一页或下一页的操作 , 增加或删除相应的 DOM即可 。 最后贴一下稍微完整一些的代码(稍微加了一些注释) 。

  1. 获取分片
/** * 获取分片 * @param fid 文件ID * @param md5 文件唯一标识 * @param token 授权码 * @param num 第N个分片 * @param showPage 显示第N个分片中的第X页 * @param speaker 是否为主讲人 * @param render 是否直接渲染 * @param clear 是否清除原有内容 */public getFragmentation( fid: number, md5: string, token: string, num: number = 0, showPage = 1, speaker?: boolean, render?: boolean, clear?: boolean): Promise { const url = `${process.env.VUE_APP_PROXY_SERVER}/${md5}-${num}.pdf?id=${fid} let promise = PDFJS.getDocument({url,cMapUrl,cMapPacked: true }).promise; promise.then((pdf: any) => {/** 记录 PDFDocumentProxy 对象, 可避免重复请求已经请求过的分片 */this.files.page = showPage;if (!this.files.pdfs) this.files.pdfs = {} as any;this.files.pdfs[num] = pdf; }); /** 是否执行渲染操作 */ if (render) {/** 清除 */if (clear) {const documents = this.getContainer() as HTMLDivElement;if (documents) documents.innerHTML = '';}/** 渲染 - 重新赋值 promise, 保证加载完成后的操作时序 */promise = new Promise((resolve) => {promise.then((pdf: any) => {/** 开始遍历循环 */for (let i = 1; i


推荐阅读