pdf 文件预览功能;中文,签名不显示解决;卡顿,渲染慢,崩溃解决;
pdf 文件预览功能;中文,签名不显示解决;卡顿,渲染慢,崩溃解决;第一种方法:vue-pdf,第二种方法:pdf.js第一种方法:vue-pdf,安装vue-pdf插件执行指令:npm install vue-pdf --saveimport pdf from "vue-pdf";<pdf v-for="i in numPages" :key="i" :src="src" :page="i
pdf 文件预览功能;中文,签名不显示解决;卡顿,渲染慢,崩溃解决;
第一种方法:vue-pdf,
安装vue-pdf插件
执行指令:npm install vue-pdf --save
import pdf from "vue-pdf";
<pdf v-for="i in numPages" :key="i" :src="src" :page="i"></pdf>
data() {
return {
src: "pdf文件加载路径",
numPages: undefined,
};
},
this.src = pdf.createLoadingTask({
url: this.pdfData.url
});
this.src.promise
.then(pdf => {
this.numPages = pdf.numPages;
})
.catch(err => {
console.log("err", err);
});
注意:这样写并没有结束。大部分pdf可正常显示,但是对一些发票pdf文件内容缺失。还要进行修改
对上面的代码进行修改
import pdf from "vue-pdf";
import CMapReaderFactory from "vue-pdf/src/CMapReaderFactory.js";
this.src = pdf.createLoadingTask({
url: this.pdfData.url,
CMapReaderFactory
});
this.src.promise
.then(pdf => {
this.numPages = pdf.numPages;
})
.catch(err => {
console.log("err", err);
});
这种方法简单,但是缺点是如果PDF文件非常大。导致整个浏览器崩溃
补充:可以实现大文件滚动分页渲染解决浏览器崩溃问题
在包裹pdf显示外层div添加滚动事件
document
.getElementById(_this.overflowId)
.addEventListener("scroll", _this.scrool);
this.src = pdf.createLoadingTask({
url: this.pdfData.url
});
this.src.promise
.then(pdf => {
// this.numPages = pdf.numPages;
// 重点:这里初始渲染的页数不需要显示总页数,可以自己定义设置想要的页数如初始显示15页,显示少一些就不会卡顿了
this.totalPage = pdf.numPages
this.numPages = 15
})
.catch(err => {
console.log("err", err);
});
scrool() {
// 滚动渲染pdf下一页
let _this = this;
const el = document.getElementById(this.overflowId);
const offsetHeight = el.offsetHeight;
el.onscroll = () => {
const scrollTop = el.scrollTop;
const scrollHeight = el.scrollHeight;
if (offsetHeight + scrollTop - scrollHeight >= -1) {
// 在这里处理判断这个逻辑滚动渲染接下来的页面
if( this.numPages< this.totalPage){
this.numPages++
}
}
};
},
第二种方法:pdf.js
网上下载pdf.js相关库文件,下载地址:https://mozilla.github.io/pdf.js/getting_started/#download
下载pdf.min.js,pdf.worker.min.js两个文件(版本@2.8.335),也可以直接线上引用,我这里是下载到本地
<script src="/pdfJS/pdf.min.js"></script>
<script src="/pdfJS/pdf.worker.min.js"></script>
data() {
return {
loadedRatio: 0, // 进度
isError: false, // 搜索pdf文件数据出错
idTemplate: "cw-pdf-", //创建pdf每一页的canvas的id统一前半部分名称
indexOfPage: 1, // 页码
pdfPage: null, // 每一页的数据对象
totalPage: 0 // 总共页数,
};
},
mounted() {
this.$nextTick(() => {
document
.getElementById(this.overflowId)
.addEventListener("scroll", this.scrool);
this.isError = false;
this.loadedRatio = 0;
this.loadPDF();
});
},
scrool() {
// 滚动渲染pdf下一页
let _this = this;
const el = document.getElementById(this.overflowId);
const offsetHeight = el.offsetHeight;
el.onscroll = () => {
const scrollTop = el.scrollTop;
const scrollHeight = el.scrollHeight;
if (offsetHeight + scrollTop - scrollHeight >= -1) {
_this.indexOfPage++;
if (_this.indexOfPage <= this.totalPage) {
let id = _this.idTemplate + _this.indexOfPage;
//根据页码创建画布
_this.createSeriesCanvas(id);
//将pdf渲染到画布上去
_this.renderPDF(_this.pdfPage, _this.indexOfPage, id);
}
}
};
},
loadPDF() {
let _this = this;
var url = this.pdfData.url;
// pdfjsDistBuildPdf.GlobalWorkerOptions.workerSrc = "/pdfJS/pdf.worker.js";
var loadingTask = pdfjsLib.getDocument({
url: url,
cMapUrl: "https://unpkg.com/pdfjs-dist@2.8.335/cmaps/",
cMapPacked: true
});
loadingTask.onProgress = function(evt) {
_this.$set(_this, "loadedRatio", evt.loaded / _this.pdfData.size);
};
loadingTask.promise
.then(function(pdf) {
//用 promise 获取页面
_this.pdfPage = pdf;
var id = "";
var pageNum = pdf.numPages;
_this.totalPage = pageNum;
let length = 15; //初始默认显示15页
if (pageNum < length) {
length = pageNum;
}
for (let i = 1; i <= length; i++) {
_this.indexOfPage = i;
id = _this.idTemplate + i;
//根据页码创建画布
_this.createSeriesCanvas(id);
//将pdf渲染到画布上去
_this.renderPDF(pdf, i, id);
}
})
.catch(err => {
let msg = this.lang["abnormal-data"];
if (document.getElementById("pdf-container")) {
document.getElementById(
"pdf-container"
).innerHTML = `<div class='text-center' style='color:red;line-height:80px;'>${msg}</div>`;
}
this.loadedRatio = 0;
this.isError = true;
});
},
renderPDF(pdf, i, id) {
console.log(i, id);
pdf.getPage(i).then(function(page) {
let scale = 2.5;
var viewport = page.getViewport({ scale: scale });
let popWidth = document.getElementById("pdf-container")
? document.getElementById("pdf-container").offsetWidth
: 0;
//判断当前弹框的宽度小于PDF文件的宽度时,将viewport和scale的值重新2倍赋值
if (popWidth && popWidth < viewport.width) {
scale = (popWidth / viewport.width) * 2.5;
viewport = page.getViewport({ scale: scale });
}
var canvas = document.getElementById(id);
var context = canvas.getContext("2d");
canvas.height = viewport.height;
canvas.width = document.getElementById("pdf-container").offsetWidth;
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
},
createPdfContainer(id, className) {
var pdfContainer = document.getElementById("pdf-container");
var canvasNew = document.createElement("canvas");
canvasNew.id = id;
canvasNew.className = className;
var br = document.createElement("br"); //添加上br元素,防止页面变大时候pdf并排显示
pdfContainer.appendChild(br);
pdfContainer.appendChild(canvasNew);
},
createSeriesCanvas(idTemplate) {
this.createPdfContainer(idTemplate, "pdfClass");
}
注意:代码中,这cMapUrl,cMapPacked两个是重点关注,这两个是处理发票内不显示的中文等缺失的内容,cMapUrl内的加载的是这个版本内cmaps文件夹中所有的.bcmap文件,也可以下载到本地项目中引入
var loadingTask = pdfjsLib.getDocument({
url: url,
cMapUrl: "https://unpkg.com/pdfjs-dist@2.8.335/cmaps/",
cMapPacked: true
});
之前参照网上其他的写法(如下)是无法起作用的。不知道是不是版本原因
pdfjsLib.cMapUrl = "https://unpkg.com/pdfjs-dist@2.8.335/cmaps/";
pdfjsLib.cMapPacked = true;
var loadingTask = pdfjsLib.getDocument(url);
这个方法相对复杂。可以加载完大文件后对数据进行处理,采用分页滚动加载显示,解决浏览器卡顿,渲染慢,崩溃问题。缺点:移动端会导致内容模糊严重,可能是scale,widht,height等配置不适合问题。
补充1:
发现新问题:huawei mate 40 pro手机 google浏览器 打开发现加载不出pdfjsLib对象。貌似其他部分手机也出现。不知道是不是新手机还是新的google版本的出现这个问题,华为自带的浏览器是可以打开pdf文件,没有问题。有解决方法的,欢迎指教
解决:pdf.js使用2.8.335(2021)版本发现有些移动google浏览器不能打开,还原使用2020年的相关版本解决问题。
更多推荐
所有评论(0)