前言
关于前端预览pdf,最简单的方式是使用window.open()
直接在浏览器的新窗口打开就好,浏览器本身也是提供了非常多的功能
但是因为客户的某些需求,不能使用浏览器自身的功能。后来又使用了 https://github.com/gjTool/pdfh5,也挺好用的,操作比较简单。使用了一段时间吧,但是还是由于客户的某些需求,最终还是放弃了。
百度查询了一下可以使用 https://github.com/mozilla/pdf.js 来实现功能自定义。
pdfjs
官方文档、examples、API
https://mozilla.github.io/pdf.js/
安装
npm install pdfjs-dist
我的版本是3.0.279
,不同版本可能有些不同。如果你是vue2加webpack的项目建议用2.6.347
,因为我在老项目中用新版本遇到了各种各样的问题。
加载
<script setup lang="ts">
import { onMounted } from 'vue';
onMounted(async() => {
const pdfjs = await import('pdfjs-dist/build/pdf.js');
const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
console.log('pdf', pdfjs);
// 加载pdf文件,本地文件会有跨域问题,使用线上文件
const url = 'http://....2022-11-07/69c075093c9942dea7dcf86ac691ff9d.pdf';
pdfjs.getDocument(url)
.promise.then(pdfDoc => {
console.log('内容:', pdfDoc, pdfDoc.numPages);
});
});
</script>
必须异步加载,不然会报错。解决方案来源于:https://github.com/mozilla/pdf.js/issues/10478
渲染
每个PDF页面都有自己的视口,它定义了以像素为单位的大小(72DPI)和初始旋转。默认情况下,视口缩放为PDF 的原始大小,但这可以通过修改视口来更改。创建视口时,还将创建一个初始变换矩阵,该矩阵考虑了所需的比例、旋转,并变换坐标系(PDF中的 0,0 点记录在左下角,而画布 0,0 在左上角)。
<template>
<div>
<div class="tool-bar">
<div>{{ pdfParams.pageNumber }} / {{ pdfParams.total }}</div>
<el-button type="primary" :disabled="pdfParams.pageNumber == pdfParams.total" @click="nextPage">下一页
</el-button>
<el-button type="primary" :disabled="pdfParams.pageNumber == 1" @click="prevPage">上一页</el-button>
<el-button type="primary" @click="rotatePage">旋转</el-button>
<el-button type="primary" :disabled="pdfParams.scale==5" @click="toBig">放大</el-button>
<el-button type="primary" :disabled="pdfParams.scale==1" @click="toSmall">缩小</el-button>
</div>
<canvas id="pdf-render"></canvas>
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive } from 'vue';
const pdfParams = reactive({
pageNumber: 1, // 当前页
total: 0, // 总页数
scale: 1, // 缩放
rotate: 0 // 旋转角度
});
// 不要定义为ref或reactive格式,就定义为普通的变量
let pdfDoc = null;
onMounted(async() => {
const pdfjs = await import('pdfjs-dist/build/pdf.js');
const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;
// 加载pdf文件,本地文件会有跨域问题,下面这个地址是不对的,自行更换
const url = 'http://y2/2022-11-07/69c075093c9942dea7dcf86ac691ff9d.pdf';
pdfjs.getDocument(url)
.promise.then(doc => {
pdfDoc = doc;
console.log('内容:', doc, doc.numPages);
pdfParams.total = doc.numPages;
getPdfPage(1);
});
});
// 加载pdf的某一页
const getPdfPage = (number) => {
pdfDoc.getPage(number).then((page) => {
console.log('page:', page);
// 获取视图,并设置缩放
const viewport = page.getViewport(
{
scale: pdfParams.scale, // 缩放
rotation: pdfParams.rotate // 旋转
});
console.log('视图:', viewport);
const outputScale = window.devicePixelRatio || 1;
// 获取canvas
const canvas = document.getElementById('pdf-render');
const context = canvas.getContext('2d');
// 设置canvas的宽高
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
canvas.style.width = Math.floor(viewport.width) + 'px';
canvas.style.height = Math.floor(viewport.height) + 'px';
// 渲染pdf
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
});
};
// 前一页
const prevPage = () => {
if (pdfParams.pageNumber > 1) {
pdfParams.pageNumber -= 1;
} else {
pdfParams.pageNumber = 1;
}
// 重新渲染
getPdfPage(pdfParams.pageNumber);
};
// 下一页
const nextPage = () => {
if (pdfParams.pageNumber < pdfParams.total) {
pdfParams.pageNumber += 1;
} else {
pdfParams.pageNumber = pdfParams.total;
}
// 重新渲染
getPdfPage(pdfParams.pageNumber);
};
// 旋转
const rotatePage = () => {
pdfParams.rotate += 90;
// 重新渲染
getPdfPage(pdfParams.pageNumber);
};
// 放大
const toBig = () => {
if (pdfParams.scale < 5) {
pdfParams.scale += 0.5;
} else {
pdfParams.scale = 5;
}
// 重新渲染
getPdfPage(pdfParams.pageNumber);
};
// 缩小
const toSmall = () => {
if (pdfParams.scale > 1) {
pdfParams.scale -= 0.5;
} else {
pdfParams.scale = 1;
}
// 重新渲染
getPdfPage(pdfParams.pageNumber);
};
</script>
<style lang="scss" scoped>
.tool-bar {
position: fixed;
z-index: 200;
left: 200px;
}
</style>
效果
补充
注意:
可以修改的属性如下图:
1、其他属性都比较好理解,transform
和 viewBox
暂时没有弄明白,不建议修改
2、旋转属性:rotation
,如果使用pdfjs提供的方式进行旋转的话要注意旋转的角度必须是90的整数倍。
3、放大的最大倍数是5被
下载
关于下载的功能我没有写,有需要的可以使用FileSaver.js
,基本使用见我的这篇文章:FileSaver.js的简单使用文章来源:https://www.toymoban.com/news/detail-518141.html
打印
打印功能有需要的话可以看我的这篇文章:前端使用print.js实现打印文章来源地址https://www.toymoban.com/news/detail-518141.html
到了这里,关于前端pdf预览、pdfjs的使用的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!