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>
相关推荐
Rhys..8 分钟前
js-箭头函数
开发语言·javascript·ecmascript
资深低代码开发平台专家11 分钟前
厌倦JavaScript 框架桎梏?Still.js:用原生之力,解遗留系统之困
开发语言·javascript·ecmascript
纟 冬15 分钟前
Flutter & OpenHarmony 运动App运动目标设定组件开发
开发语言·javascript·flutter
2501_9444460015 分钟前
Flutter&OpenHarmony应用内导航与路由管理
开发语言·javascript·flutter
小徐不会敲代码~24 分钟前
Vue3 学习 5
前端·学习·vue
_Kayo_25 分钟前
vue3 状态管理器 pinia 用法笔记1
前端·javascript·vue.js
How_doyou_do25 分钟前
工程级前端智能体FrontAgent
前端
2501_9462338930 分钟前
Flutter与OpenHarmony Tab切换组件开发详解
android·javascript·flutter
daols8830 分钟前
vue 甘特图 vxe-gantt table 可视化依赖线的使用,可视化拖拽创建连接线的用法
vue.js·甘特图·vxe-table
3秒一个大31 分钟前
LangChain 中的 Output 解析器与 Zod:用法与意义
javascript·langchain