web、H5、vue等预览pdf文件(Pdf.js)
Pdf.js官方文档:文档地址
1. 使用场景
- 在浏览器中展示PDF文件内容:使用Html5的canvas元素来展示pdf文件。
- 支持基本的浏览功能:PDF.js提供了一套用户界面,包括缩放、滚动、翻页等浏览功能,使用户能够方便地导航和浏览PDF文件。
2. 使用方法
-
web浏览器中使用
-
引入pdf.js文件.需要使用pdf.js文件和pdf.worker.js文件。
// 引入 pdf.js 文件 <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.js"></script>
-
编码示例(2.x版本示例)
<!DOCTYPE html> <html> <head> <title>PDF.js Example</title> <style> #pdf-container { width: 800px; height: 600px; overflow: scroll; } </style> </head> <body> <div id="pdf-container"></div> <button id="prev-btn">Previous</button> <button id="next-btn">Next</button> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.js"></script> <script> // 指定工作线程脚本的路径 pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.js' var container = document.getElementById('pdf-container') // 放入pdf文件链接地址 pdfjsLib.getDocument('https://oss.xxxxxxxxxxxxx.pdf').promise.then(function (pdf) { var currentPage = 1 function renderPage(pageNumber) { container.innerHTML = '' // 清空容器 pdf.getPage(pageNumber).then(function (page) { var scale = 1.2 var viewport = page.getViewport({ scale: scale }) var canvas = document.createElement('canvas') var context = canvas.getContext('2d') canvas.width = viewport.width canvas.height = viewport.height page.render({ canvasContext: context, viewport: viewport }) container.appendChild(canvas) currentPage = pageNumber }) } // 监听翻页按钮点击事件 document.getElementById('prev-btn').addEventListener('click', function () { if (currentPage > 1) { renderPage(currentPage - 1) } }) document.getElementById('next-btn').addEventListener('click', function () { if (currentPage < pdf.numPages) { renderPage(currentPage + 1) } }) renderPage(1) }) </script> </body> </html>
-
最新版本(4.x)示例
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>pdf example</title> </head> <body> <canvas id="the-canvas" style="border: 1px solid black; direction: ltr;"></canvas> <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.min.mjs" type="module"></script> <script id="script" type="module"> // url是pdf文件的链接地址 const url = 'https://oss.xxxxxxxxxxx.pdf' pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.worker.mjs' const loadingTask = pdfjsLib.getDocument(url) const pdf = await loadingTask.promise const page = await pdf.getPage(1) const scale = 1.5 const viewport = page.getViewport({ scale }) const outputScale = window.devicePixelRatio || 1 const canvas = document.getElementById("the-canvas") const context = canvas.getContext("2d") 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" const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null const renderContext = { canvasContext: context, transform, viewport, } page.render(renderContext) </script> <pre id="code"></pre> </body> </html>
-
-
vue3组件中使用(直接上代码)
<template> <div class="pdf-container" v-loading="loading"> <canvas id="the-canvas"></canvas> <div class="change-page-btns"> <el-button type="primary" @click="changePage('prev')">上一页</el-button> <span> {{ currPageNum }} / {{ pageTotal }} </span> <el-button type="primary" @click="changePage('next')">下一页</el-button> </div> </div> </template> <script setup lang="ts"> /** * 在npm.org modules 市场没有找到对应的 pdf.js 应用,所以这里继续使用cdn网络,或者把代码下载到本地调用 * https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.worker.mjs * https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.mjs */ import * as pdfjsLib from 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.mjs' import { ref, onMounted, reactive} from 'vue' import { ElMessage } from 'element-plus' const filePath = ref('https://oss.xxxxx.pdf') // 要展示的pdf文件链接地址 const loading = ref(false) let CurrPdfInfo:any = reactive({}) const pageTotal = ref(1) const currPageNum = ref(1) // 默认展示pdf文件的第一页 onMounted(() => { init() }) const init = async () => { currPageNum.value = 1 loading.value = true pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.1.392/pdf.worker.mjs' const loadingTask = pdfjsLib.getDocument(filePath.value) CurrPdfInfo = await loadingTask.promise pageTotal.value = CurrPdfInfo.numPages || 0 loading.value = false RenderPage() } const RenderPage = async () => { const page = await CurrPdfInfo.getPage(currPageNum.value) const scale = 1 const viewport = page.getViewport({ scale }) const outputScale = window.devicePixelRatio || 1 const canvas:any = document.getElementById("the-canvas") || null const context:any = canvas.getContext("2d") 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" const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null const renderContext = { canvasContext: context, transform, viewport, } page.render(renderContext) } const changePage = (type:string) => { if (currPageNum.value === 1 && type === 'prev') { ElMessage.info('您已经操作到第一页!') } else if (currPageNum.value === pageTotal.value && type === 'next') { ElMessage.info('您已经操作到最后一页!') } else { if (type === 'prev') { // 上一页 currPageNum.value > 1 ? currPageNum.value-- : currPageNum.value = 1 } else if (type === 'next') { // 下一页 CurrPdfInfo currPageNum.value < pageTotal.value ? currPageNum.value++ : currPageNum.value = pageTotal.value } RenderPage() } } </script> <style scoped> .pdf-container { width: 100%; height: 800px; border: 1px solid red; overflow: scroll; } </style>
-
uni-app H5中使用(新版本参考vue实现方式),以下是 **@dcloudio/uni-app-plus -v2.0.0 **为例来实现。---uniapp其他打包方式有原生api支持:uni.openDocument(OBJECT)。
// 此代码仅使用与uniapp打包成H5适用, 其他打包方式uni.openDocument(OBJECT)原生方法即可实现。 // 项目入口index.html文件中要引入 js 文件 // <script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.js"></script> <template> <scroll-view class="scroll-container" @scrolltoupper="loadPerPage" @scrolltolower="loadNextPage" scroll-y="true" scroll-x="true"> <view id="pdf-container"></view> </scroll-view> </template> <script> export default { name: 'scanPdf', data () { return { infoData: '', container: null, // 渲染pdf的canvas容器 currPageNum: 1, // 默认渲染第一页 pageTotal: 1, loadPageCount: 1, CurrPdfInfo: null, url: 'https://oss.xxxx/demo-ui.pdf' } }, mounted () { this.initPdfViewer() }, methods: { initPdfViewer () { this.currPageNum = 1 this.loading = true uni.showLoading({title: '文件加载中...'}) pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.worker.js' this.container = document.getElementById('pdf-container') pdfjsLib.getDocument(this.url).promise.then(pdf => { uni.hideLoading() this.pageTotal = pdf.numPages || 0 // pdf文件共有多少页 this.CurrPdfInfo = pdf this.renderPage() // 初始化完成数据默认渲染第一页 }) }, renderPage () { // this.container.innerHTML = '' // 清空容器 this.CurrPdfInfo.getPage(this.currPageNum).then(page => { const scale = 1 const viewport = page.getViewport({ scale: scale }) const canvas = document.createElement('canvas') const context = canvas.getContext('2d') canvas.width = viewport.width canvas.height = viewport.height page.render({ canvasContext: context, viewport: viewport }) this.container.appendChild(canvas) }) }, loadNextPage () { if (this.loadPageCount <= this.currPageNum) { if (this.currPageNum < this.pageTotal) { this.currPageNum++ this.loadPageCount = this.currPageNum this.renderPage() } else { this.currPageNum = this.pageTotal uni.showToast({ title: '已经浏览到最后一页啦!', icon: 'none', mask: false }) } } }, loadPerPage () { uni.showToast({ title: '已经浏览到第一页啦!', icon: 'none', mask: false }) } } } </script> <style scoped> .scroll-container { width: 100%; height: 100%; } </style>
- 有其他适配后续更新