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>
相关推荐
「、皓子~12 分钟前
后台管理系统的诞生 - 利用AI 1天完成整个后台管理系统的微服务后端+前端
前端·人工智能·微服务·小程序·go·ai编程·ai写作
就改了15 分钟前
Ajax——在OA系统提升性能的局部刷新
前端·javascript·ajax
凌冰_17 分钟前
Ajax 入门
前端·javascript·ajax
京东零售技术32 分钟前
京东小程序JS API仓颉改造实践
前端
奋飛41 分钟前
TypeScript系列:第六篇 - 编写高质量的TS类型
javascript·typescript·ts·declare·.d.ts
老A技术联盟41 分钟前
从小白入门,基于Cursor开发一个前端小程序之Cursor 编程实践与案例分析
前端·小程序
风铃喵游1 小时前
构建引擎: 打造小程序编译器
前端·小程序·架构
sunbyte1 小时前
50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | ThemeClock(主题时钟)
前端·javascript·css·vue.js·前端框架·tailwindcss
小飞悟1 小时前
🎯 什么是模块化?CommonJS 和 ES6 Modules 到底有什么区别?小白也能看懂
前端·javascript·设计
浏览器API调用工程师_Taylor1 小时前
AOP魔法:一招实现登录弹窗的全局拦截与动态处理
前端·javascript·vue.js