vant4+vue3上传一个pdf文件并实现pdf的预览。使用插件pdf.js

注意下载的插件的版本"pdfjs-dist": "^2.2.228",

npm i  pdfjs-dist@2.2.228

然后封装一个pdf的遮罩。因为pdf文件有多页,所以我用了swiper轮播的形式展示。因为用到移动端,手动滑动页面这样比点下一页下一页的方便多了。

直接贴代码了

PdfPreview/index.vue

<!--预览pdf文件的组件-->
<template><van-overlay :show="show" @click="close()"><div class="pdf-viewer" ><van-swipe class="my-swipe" indicator-color="red" @click.stop><van-swipe-item v-for="item in pageNum" :key="item"><canvas :id="`pdf-canvas-${item}`" class="pdf-page"/></van-swipe-item><template #indicator="{ active, total }"><div class="custom-indicator">{{ active + 1 }}/{{ total }}</div></template></van-swipe><van-emptyv-if="loadError"image="error"description="PDF加载出错了..."/></div><van-icon name="close" color="#fff" size="0.3rem"/></van-overlay></template><script setup lang="tsx">
import {ref, nextTick, watch} from 'vue';
import {closeToast, showLoadingToast, showSuccessToast} from "vant";// 引入pdf预览插件相关的参数,注意这块开始试了很多网上方法都不好用
import * as pdfjs from 'pdfjs-dist';
import pdfjsWorker from 'pdfjs-dist/build/pdf.worker?url';
// 设置 worker 路径
pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker;const show = ref(true);
// html部分涉及的参数
const loadError = ref(false);
const detail = ref({});
let pdfDoc = null; // 一定不能使用响应式的数据,会报错Cannot read from private field---pdf.js
const pageNum = ref(0);const props = defineProps({pdfUrl: {type: String,default: ""},
})
const emit= defineEmits(['close'])watch(() => props.pdfUrl, (newVal) => {// console.log("监听", newVal, props.pdfUrl)showLoadingToast('加载中');nextTick(() => {loadingPdf(props.pdfUrl); })}, {immediate: true,deep:true})
// 防抖 debounce 函数的实现正确。
const debounce(func, wait, options = {}) {let timeout;const { leading = false, trailing = true } = options;return function(...args) {const later = () => {timeout = null;if (!leading) func.apply(this, args);};const callNow = leading && !timeout;clearTimeout(timeout);timeout = setTimeout(later, wait);if (callNow) func.apply(this, args);};
}
// 使用防抖函数,300ms内只执行一次,避免多次点击立刻打开又关闭的情况
const close = debounce(() => {show.value = false;emit('close')
}, 300, { leading: true, trailing: false });//加载pdf
const loadingPdf = (url) => {const afterUrl = {url,httpHeaders: {token: `Bearer-${localStorage.getItem('token')}`,//微信小程序里面打开这个模块,发现请求401,报错信息是登陆访问超时,发现pdfjs加载pdf时没有携带token,于是在加载url时添加token即可},};const loadingTask = pdfjs.getDocument(afterUrl);loadingTask.promise.then((pdf) => {pdfDoc = pdf;pageNum.value = pdf.numPages;  nextTick(() => {renderPage();});}).catch(() => {loadError.value = true;});
}// 渲染pdf
const renderPage = (num = 1) => {pdfDoc.getPage(num).then((page) => {const canvas = document.getElementById(`pdf-canvas-${num}`); if(!canvas){return}const ctx = canvas.getContext('2d');const scale = 1.5;const viewport = page.getViewport({scale});// 画布大小,默认值是width:300px,height:150pxcanvas.height = viewport.height;canvas.width = viewport.width;// 画布的dom大小, 设置移动端,宽度设置铺满整个屏幕const {clientWidth} = document.body;// 减去2rem使用因为我的页面左右加了paddingcanvas.style.width = `calc(${clientWidth}px - 2rem)`;// 根据pdf每页的宽高比例设置canvas的高度canvas.style.height = `${clientWidth * (viewport.height / viewport.width)}px`;canvas.height = viewport.height;canvas.width = viewport.width;page.render({canvasContext: ctx,viewport,});//隐藏渲染所有的页面if (num < pageNum.value) {renderPage(num + 1);} else {closeToast();}});
}</script><style scoped>
.pdf-viewer{display: flex;justify-content: center;align-items: center;height:100vh;width:100vw;text-align: center;
}
.custom-indicator {position: absolute;left: 50%;bottom: 15px;transform: translateX(-50%);padding: 2px 5px;font-size: 18px;color: #fff;background: rgba(0, 0, 0, 0.1);
}
</style>

上传的页面先按照这个地址这篇文章写好。稍微改动一下就可以了vant4+vue3封装一个上传公共组件.有上传和删除访问接口的过程。限制上传的格式和上传文件大小-CSDN博客

然后给组件添加一个点击预览的事件 。并把上面写好的预览组件引入

import PdfPreview from "@/components/PdfPreview/index.vue";
// 点击预览文件
const showPreview=(file)=>{if(file.absoluteUrl.endsWith('.pdf')){pdfUrl.value=file.absoluteUrl;preview.value=true;}
}

遇到的问题:

如果报错Uncaught (in promise) TypeError: Cannot read properties of null (reading 'getContext')

可能是canvas要找的那个id在页面还没有渲染出来。所以我用的nextTick,还在获取canvas后面判断了一下找到了再继续 ,注意上面棕色加粗的地方。


如果报错vue-router.mjs:3518SyntaxError: The requested module '/node_modules/.vite/deps/pdfjs-dist_build_pdf__worker__entry.js?v=8ae4d11f' does not provide an export named 'default'

检查一下你引入插件的地方。如果是

import pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';这样写的就是错的

改成

import pdfjsWorker from 'pdfjs-dist/build/pdf.worker?url';

问题:如果你点击第一次弹窗展示了,但是再点击就没有弹出。

原因是预览的组件渲染是监听的pdf的url的地址。如果你第一个打开没有把组件销毁。那么再次显示的时候没有走监听。就不会显示。所以要在每次关闭弹窗是组件也销毁。这就是上面我要在子组件中用@close给组件通知让他不显示也就是销毁子组件的原因。


问题:无意间双击了文件导致遮罩马上显示又隐藏。页面效果就是黑色遮罩闪了一下。

可以使用防抖的方式。延迟关闭。参考上面紫色的关闭函数

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/75427.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Leetcode hot 100(day 4)

翻转二叉树 做法&#xff1a;递归即可&#xff0c;注意判断为空 class Solution { public:TreeNode* invertTree(TreeNode* root) {if(rootnullptr)return nullptr;TreeNode* noderoot->left;root->leftinvertTree(root->right);root->rightinvertTree(node);retu…

C,C++语言缓冲区溢出的产生和预防

缓冲区溢出的定义 缓冲区是内存中用于存储数据的一块连续区域&#xff0c;在 C 和 C 里&#xff0c;常使用数组、指针等方式来操作缓冲区。而缓冲区溢出指的是当程序向缓冲区写入的数据量超出了该缓冲区本身能够容纳的最大数据量时&#xff0c;额外的数据就会覆盖相邻的内存区…

大数据(4)Hive数仓三大核心特性解剖:面向主题性、集成性、非易失性如何重塑企业数据价值?

目录 背景&#xff1a;企业数据治理的困境与破局一、Hive数据仓库核心特性深度解析1. ‌面向主题性&#xff08;Subject-Oriented&#xff09;&#xff1a;从业务视角重构数据‌2. ‌集成性&#xff08;Integrated&#xff09;&#xff1a;打破数据孤岛的统一视图‌3. ‌非易失…

A股复权计算_前复权数据计算_终结章

目录 前置&#xff1a; 计算方法推导 数据&#xff1a; 代码&#xff1a; 视频&#xff1a; 前置&#xff1a; 1 本系列将以 “A股复权计算_” 开头放置在“随想”专栏 2 权息数据结合 “PostgreSQL_” 系列博文中的股票未复权数据&#xff0c;可以自行计算复权日数据 …

Nature:新发现!首次阐明大脑推理神经过程

人类具有快速适应不断变化的环境的认知能力。这种能力的核心是形成高级、抽象表示的能力&#xff0c;这些表示利用世界上的规律来支持泛化。然而&#xff0c;关于这些表征如何在神经元群中编码&#xff0c;它们如何通过学习出现以及它们与行为的关系&#xff0c;人们知之甚少。…

Kotlin 集合函数:map 和 first 的使用场景

Kotlin 提供了丰富的集合操作函数&#xff0c;使开发者可以更加简洁、高效地处理数据。其中&#xff0c;map 和 first 是两个常用的函数&#xff0c;分别用于转换集合和获取集合中的第一个元素。 1. map 的使用场景 场景 1&#xff1a;对象列表转换 在开发中&#xff0c;我们…

EIR管理中IMEI和IMSI信息的作用

在EIR&#xff08;设备身份注册&#xff09;管理中&#xff0c;IMEI&#xff08;国际移动设备身份码&#xff09;和IMSI&#xff08;国际移动用户识别码&#xff09;各自具有重要作用&#xff0c;以下是详细介绍&#xff1a; IMEI的作用 设备身份识别&#xff1a;IMEI是移动设…

MAUI开发第一个app的需求解析:登录+版本更新,用于喂给AI

vscode中MAUI框架已经搭好,用MAUI+c#webapi+orcl数据库开发一个app, 功能是两个界面一个登录界面,登录注册常用功能,另一个主窗体,功能先空着,显示“主要功能窗体”。 这是一个全新的功能,需要重零开始涉及所有数据表 登录后检查是否有新版本程序,自动更新功能。 1.用户…

KUKA机器人查看运行日志的方法

对于KUKA机器人的运行日志都是可以查看和导出的&#xff0c;方便查找问题。KUKA机器人的运行日志查看方法如下&#xff1a; 1、在主菜单下&#xff0c;选择【诊断】-【运行日志】-【显示】下打开&#xff1b; 2、显示出之前的机器人运行日志&#xff1b; 3、也可以通过【过滤器…

Kali Linux 2025.1a:主题焕新与树莓派支持的深度解析

一、年度主题更新与桌面环境升级 Kali Linux 2025.1a作为2025年的首个版本&#xff0c;延续了每年刷新主题的传统。本次更新包含全新的启动菜单、登录界面及桌面壁纸&#xff0c;涵盖Kali标准版和Kali Purple版本。用户可通过安装kali-community-wallpapers包获取社区贡献的额…

【UVM学习笔记】更加灵活的UVM—通信

系列文章目录 【UVM学习笔记】UVM基础—一文告诉你UVM的组成部分 【UVM学习笔记】UVM中的“类” 文章目录 系列文章目录前言一、TLM是什么&#xff1f;二、put操作2.1、建立PORT和EXPORT的连接2.2 IMP组件 三、get操作四、transport端口五、nonblocking端口六、analysis端口七…

uni-app项目上传至gitee方法详细教程

1. 准备工作 1.1 安装 Git 下载并安装 Git&#xff1a;前往 Git 官网&#xff0c;根据操作系统下载安装包。 配置用户名和邮箱&#xff08;需与 Gitee 账号一致&#xff09;&#xff1a; git config --global user.name "你的Gitee用户名" git config --global use…

走向多模态AI之路(三):多模态 AI 的挑战与未来

目录 前言一、多模态 AI 真的成熟了吗&#xff1f;二、多模态 AI 的主要挑战2.1 计算资源消耗&#xff1a;模型复杂度带来的成本问题2.2 数据标注困难&#xff1a;跨模态数据集的挑战2.3 对齐和融合的难点2.4 泛化能力与鲁棒性2.5 伦理与隐私问题 三、研究方向与未来发展3.1 轻…

STM32单片机入门学习——第12节: [5-2]对射式红外传感器计次旋转编码器计次

写这个文章是用来学习的,记录一下我的学习过程。希望我能一直坚持下去,我只是一个小白,只是想好好学习,我知道这会很难&#xff0c;但我还是想去做&#xff01; 本文写于&#xff1a;2025.04.03 STM32开发板学习——第12节: [5-2]对射式红外传感器计次&旋转编码器计次 前言…

汇编学习之《jcc指令》

JCC&#xff08;Jump on Condition Code&#xff09;指的是条件跳转指令&#xff0c;c中的就是if-else, while, for 等分支循环条件判断的逻辑。它包括很多指令集&#xff0c;各自都不太一样&#xff0c;接下来我尽量将每一个指令的c 源码和汇编代码结合起来看&#xff0c;加深…

深度解析算法之滑动窗口

12滑动窗口—将 x 减到 0 的最小操作数 题目传送门 题目描述&#xff1a; 给你一个整数数组 nums 和一个整数 x 。每一次操作时&#xff0c;你应当移除数组 nums 最左边或最右边的元素&#xff0c;然后从 x 中减去该元素的值。请注意&#xff0c;需要 修改 数组以供接下来的操…

[MySQL初阶]MySQL表的操作

MySQL表的操作 1. 创建表2. 查看表结构3. 修改表&#xff08;修改表的属性而非表的数据&#xff09;4. 删除表 1. 创建表 语法&#xff1a; CREATE TABLE table_name (field1 datatype,field2 datatype,field3 datatype ) character set 字符集 collate 校验规则 engine 存储…

sqlalchemy详细介绍以及使用方法

SQLAlchemy是一个Python的ORM&#xff08;对象关系映射&#xff09;工具&#xff0c;它允许开发者使用Python代码来操作数据库而不必直接编写SQL语句。SQLAlchemy提供了一种抽象层&#xff0c;使开发者可以通过简单的Python对象来表示数据库表和记录&#xff0c;从而实现对数据…

图解AUTOSAR_SWS_LINDriver

AUTOSAR LIN驱动详解文档 基于AUTOSAR标准的本地互联网络(LIN)驱动程序技术规范解析 目录 1. 概述 1.1 AUTOSAR LIN驱动简介1.2 LIN协议基础2. LIN驱动架构 2.1 类图结构2.2 状态机设计3. LIN帧结构 3.1 基本帧组成3.2 PID结构4. LIN驱动配置 4.1 主要配置参数4.2 配置结构5. L…

《网络管理》实践环节03:snmp服务器上对网络设备和服务器进行初步监控

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 应用拓扑图 3.0准备工作 所有Linux服务器上&#xff08;服务器和Agent端&#xff09;安装下列工具 yum -y install net-snmp net-snmp-utils 保证所有的HCL网络设备和服务器相互间能…