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.pswp.cn/pingmian/75427.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/75427.shtml
英文地址,請注明出處:http://en.pswp.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網絡設備和服務器相互間能…