赞
踩
放大后
缩小后
也可以分页显示
选用这两个的插件是因为如果实现pdf预览其实使用iframe标签就可以的,但是使用iframe标签实现的比较臭,vue-pdf-embed是能够自定义样式的,更加灵活,我也是第一次尝试这个,也遇到了一些坑,后面会跟大家分享,反正按照这个来就能实现,源码我也放后面了。
1、我这里项目搭建是用的Vite也不知道使用vue cli会不会有什么问题
2、vue-pdf-embed我开始是pnpm i vue-pdf-embed 安装了最新的,后面会发现pdf预览不出来,找了原因是版本的问题,我就pnpm i vue-pdf-embed@1.2.1 切换到1.2.1版本就好了
3、vue3-pdfjs在这是用来做监听pdf页数的当然还有别的用处。
4、当预览成果后会发现文字并未出来,f12会报这个
warning: error during font loading: the cmap "baseurl" parameter must be specified, ensure that the "cmapurl" and "cmappacked" api parameters are provided.
原因就是缺少中文包,加上下面这段就行了,这段代码在源码里面
5、还有个问题是scale缩放开始无效,原因大概是因为在使用 vue-pdf-embed
组件的 scale
参数时发现无法实现动态更改,且 width
参数无法设置成百分比的形式,所以采用修改父容器的方案实现。
//父组件
- <template>
- <div class="main">
- <div class="home-box">
- <pdfView :pdfUrl="jsPdf"/>
- </div>
- </div>
- </template>
- <script lang="ts" setup>
- import { ref } from 'vue'
- import pdfView from '@/components/pdfView/index.vue';
- import jsPdf from './jsPdf.pdf';
- </script>
- <style lang="scss" scoped>
- .main {
- width: 100vw;
- height: 100vh;
- display: flex;
- align-items: center;
- justify-content: center;
- .home-box{
- width: 80%;
- }
- }
- </style>

子组件
- <template>
- <div class="pdf-preview">
- <div
- class="pdf-wrap"
- :style="{ transform: `translate(-50%,-50%) scale(${scaleData})` }"
- >
- <vue-pdf-embed
- :source="state.source"
- :style="state.scale"
- class="vue-pdf-embed"
- :page="state.pageNum"
- />
- </div>
- <div class="page-tool">
- <div class="page-tool-item" @click="lastPage">上一页</div>
- <div class="page-tool-item" @click="nextPage">下一页</div>
- <div class="page-tool-item">{{ state.pageNum }}/{{ state.numPages }}</div>
- <div class="page-tool-item" @click="zoomIn">放大</div>
- <div class="page-tool-item" @click="zoomOut">缩小</div>
- <div class="page-tool-item" @click="pageRest">重置缩放</div>
- </div>
- </div>
- </template>
- <script setup lang="ts">
- import { reactive, onMounted, computed, ref } from 'vue'
- import VuePdfEmbed from 'vue-pdf-embed'
- import { createLoadingTask } from 'vue3-pdfjs'
- const props = defineProps({
- pdfUrl: {
- type: String,
- required: true
- }
- })
- const state = reactive({
- source: {
- url: props.pdfUrl,
- cMapUrl: 'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.9.359/cmaps/',
- cMapPacked: true
- }, //预览pdf文件地址
- pageNum: 1, //当前页面
- scale: 1, // 缩放比例
- numPages: 0 // 总页数
- })
- const scaleData = ref(1.0)
- const pageHeight = ref('100%')
- //上一页
- function lastPage() {
- if (state.pageNum > 1) {
- state.pageNum -= 1
- }
- }
- //下一页
- function nextPage() {
- if (state.pageNum < state.numPages) {
- state.pageNum += 1
- }
- }
-
- // 放大
- function zoomIn() {
- scaleData.value += 0.1
- pageHeight.value = parseInt(pageHeight.value) - 5.0 + '%'
- }
- // 缩小
- function zoomOut() {
- scaleData.value -= 0.1
- pageHeight.value = parseInt(pageHeight.value) + 5.0 + '%'
- }
- // 页面 放大/缩小 还原默认值
- function pageRest() {
- scaleData.value = 1.0
- pageHeight.value = '100%'
- }
-
- onMounted(() => {
- // debugger
- // console.log(props.pdfUrl)
- // debugger
-
- //获取pdf总页数
- const loadingTask = createLoadingTask(state.source)
- loadingTask.promise.then((pdf: { numPages: number }) => {
- // debugger
- state.numPages = pdf.numPages
- // debugger
- })
- })
- </script>
- <style lang="scss" scoped>
- .pdf-preview {
- position: relative;
- height: 100vh;
- padding: 20px 0;
- box-sizing: border-box;
- background-color: e9e9e9;
- .pdf-wrap {
- position: absolute;
- width: 100%;
- top: 50%;
- left: 50%;
- height: 100%;
- overflow-y: auto;
- .vue-pdf-embed {
- height: 100%;
- text-align: center;
- width: 80%;
- border: 1px solid #e5e5e5;
- margin: 0 auto;
- box-sizing: border-box;
- }
- }
- .page-tool {
- position: absolute;
- bottom: 35px;
- padding-left: 15px;
- padding-right: 15px;
- display: flex;
- align-items: center;
- background: rgb(66, 66, 66);
- color: white;
- border-radius: 19px;
- z-index: 100;
- cursor: pointer;
- margin-left: 50%;
- transform: translateX(-50%);
- .page-tool-item {
- padding: 8px 15px;
- padding-left: 10px;
- cursor: pointer;
- }
- }
- }
- </style>

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。