Vue+pdfjs+turn.Js实现pdf翻页预览效果

  • 项目新需求要求实现预览用户上传的pdf文件并且要有翻书效果。 找了很多文章参考,最终使用pdfjs+turn.Js实现。
  1. 安装pdfjs插件
sql 复制代码
npm install pdfjs-dist@2.2.228 --legacy-peer-deps

2.在需要使用的页面引入

javascript 复制代码
import * as pdfjs from 'pdfjs-dist'
import * as pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry' 
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker
  1. 由于turn.js依赖JQ,所我们先安装JQ
css 复制代码
npm install jquery --save
  1. 配置JQ
  • 在vue.config.js中找到module.exports加入代码
css 复制代码
plugins: [
    new webpack.ProvidePlugin({
        jQuery: "jquery",
        $: "jquery"
    })],

结果如图:

5. 在需要使用的页面引用JQ(如果$报错可以试试在main.js中引入)

javascript 复制代码
import $ from 'jquery'
  1. 去官网下载turn.Js
  • 官网地址:www.turnjs.com/
  • 下载成功后解压包,将文件夹里的turn.js和turn.min.js引入项目。(我是放在utils文件夹里面,下图)
  1. 同样,在需要使用的页面中引入
arduino 复制代码
import turn from '@/utils/turn.js'
  1. 东西都准备好后,准备一个pdf文件(一般由后端接口返回,这里我使用的是本地文件)
  • 本地文件要放进public文件夹中,访问的时候使用"/static/xxx/xxx"的方式(如下图)
  1. 准备一个id为flipbook的盒子用来渲染pdf书(相当于一个书壳)里的的div盒子用来循环渲染这本书的每一页
ini 复制代码
<div id="flipbook">
    <div v-for="(item, index) in pdfPicturePath" :key="index" class="page" v-show="show">
        <img style="width: 100%; height: 100%" :src="item" />
    </div>
</div>

10.handlePdf函数。

  • 主要用来下载pdf。
  • 然后将pdf的每一页都转换成一张图片并将每一张图片放进一个数组中(pdfPicturePath)
  • 数据都准备好后就可以初始化turn.js生成一本书
ini 复制代码
// fileUrl = "/static/pdf/test.pdf" 这里是本地文件的地址
async handlePdf(fileUrl) {
        let that = this
        // 下载pdf文件
        const pdf = await pdfjs.getDocument(fileUrl); 
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        // 循环将pdf每一页转成图片后放入图片列表
        for (let i = 1; i <= pdf._pdfInfo.numPages; i++) {
            const page = await pdf.getPage(i);
            const viewport = page.getViewport({scale: 1});
            canvas.width = viewport.width;
            canvas.height = viewport.height;
            let renderContext = {
                canvasContext: context,
                viewport: viewport,
            };
            await page.render(renderContext).promise;
            let imgUrl = canvas.toDataURL('image/png')
            that.pdfPicturePath.push(imgUrl) 
        }
        this.show = true
        // 初始化turn.js生成一本书
        $("#flipbook").turn({
            acceleration: true, //启用硬件加速,移动端有效
            display: 'double', //显示:single=单页,double=双页,默认双页
            width: 375, // 书的宽度
            height: 627, // 书的高度
            autoCenter: true,
            turnCorners: 'bl,br', // 设置可翻页的页脚
        });
    },
  1. 最后在钩子函数里调用就好了。
  2. 如果想要点击"下一页""上一页"来翻页,那就直接放两个按钮分别添加点击事件。
javascript 复制代码
// 上一页
next() {
    $("#flipbook").turn("next");
},
// 下一页
previous() {
    $("#flipbook").turn("previous");
},
  1. 最终效果
  1. 附上整体代码
xml 复制代码
<template>
    <div>
        <div id="flipbook">
            <div v-for="(item, index) in pdfPicturePath" :key="index" class="page" v-show="show">
                <img style="width: 100%; height: 100%" :src="item" />
            </div>
        </div>
        <div style="margin-top: 2rem">
            <el-button type="" @click="next">下一页</el-button>
            <el-button type="" @click="previous">上一页</el-button>
        </div>
    </div>
</template>

<script>
import * as pdfjs from 'pdfjs-dist'
import * as pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry' 
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker
import $ from 'jquery'
import turn from '@/utils/turn.js'
export default {
  name: 'test_box1',
  data() {
    return {
        pdfPicturePath: [],
        fileUrl: '/static/pdf/test.pdf',
        show: false
    }
  },
  mounted() {   
    this.handlePdf(this.fileUrl)
  },
  methods:{
    next() {
        $("#flipbook").turn("next");
    },
    previous() {
        $("#flipbook").turn("previous");
    },
    async handlePdf(fileUrl) {
        let that = this
        const pdf = await pdfjs.getDocument(fileUrl);
        const canvas = document.createElement('canvas');
        const context = canvas.getContext('2d');
        for (let i = 1; i <= pdf._pdfInfo.numPages; i++) {
        const page = await pdf.getPage(i);
        const viewport = page.getViewport({scale: 1});
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        let renderContext = {
            canvasContext: context,
            viewport: viewport,
        };
        await page.render(renderContext).promise;
        let imgUrl = canvas.toDataURL('image/png')
        that.pdfPicturePath.push(imgUrl)
        }
        this.show = true
        $("#flipbook").turn({
            width: 375,
            height: 627,
            display: 'single',
            autoCenter: true,
            turnCorners: 'bl,br',
        });
    }
  }
};
</script>
<style lang="scss" scoped="scoped">
    .hard{
        text-align: center;
    }
    .page {
        background: pink;
        text-align: center;
    }
</style>
相关推荐
m0_7482552619 分钟前
前端安全——敏感信息泄露
前端·安全
鑫~阳2 小时前
html + css 淘宝网实战
前端·css·html
Catherinemin2 小时前
CSS|14 z-index
前端·css
漫天转悠2 小时前
Vue3项目中引入TailwindCSS(图文详情)
vue.js
qq_589568103 小时前
Echarts+vue电商平台数据可视化——后台实现笔记
vue.js·信息可视化·echarts
2401_882727573 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
NoneCoder4 小时前
CSS系列(36)-- Containment详解
前端·css
anyup_前端梦工厂4 小时前
初始 ShellJS:一个 Node.js 命令行工具集合
前端·javascript·node.js
5hand4 小时前
Element-ui的使用教程 基于HBuilder X
前端·javascript·vue.js·elementui
GDAL4 小时前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js