vue3實現pdf文件預覽 - vue-pdf-embed

參考地址:https://juejin.cn/post/7105933034771185701
這個參考文章的代碼直接可以復制使用,樣式也是給到的,但是實現的是一頁一頁的顯示pdf內容,我的需求是要全部展示出來,頁碼切換時是做一個滾動定位操作。

思路:

  1. 通過vue3-pdfjs插件提供的方法createLoadingTask獲取到總頁碼numPages,通過循環將所有頁面渲染
  2. 頁碼定位通過錨點定位方式實現。

安裝插件:

 npm install vue-pdf-embed@1.1.6npm install vue3-pdfjs@0.1.6

注意:vue-pdf-embed使用1.1.6版本,之前未固定版本出現內容不顯示問題(大概1版本的可以,2版本的不行,我這邊使用的是1.1.6版本)。vue3-pdfjs安裝就是0.1.6版本的,記錄加上版本好,防止后期有更新出現問題不知道原因。

完整代碼:

<template><div class="pdf-preview-container"><!-- 頭部導航欄 --><div class="pdf-header"><div class="page-navigation"><div class="page-controls"><!-- 上一頁按鈕 --><el-button link :disabled="state.pageNum <= 1" @click="prevPage"><el-icon><ArrowUp /></el-icon></el-button><!-- 頁碼輸入框 --><el-input v-model.number="state.pageNum" class="page-input" @keyup.enter="goToPage" @blur="goToPage" /><!-- 下一頁按鈕 :disabled="currentPage >= totalPages" --><el-button link @click="nextPage"><el-icon><ArrowDown /></el-icon></el-button></div><!-- 總頁數 --><span class="total-pages">/&nbsp;&nbsp;{{ state.numPages }}</span></div></div><!-- PDF預覽區域 --><div class="pdf-content"><!-- PDF內容顯示區域 --><div class="pdf-display-area"><div v-for="item in state.numPages" :key="item" class='pdf-item' :id="`pdf-page-${item}`"><vue-pdf-embed :source="state.source" class="vue-pdf-embed" :page="item" /></div></div></div></div>
</template><script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch, computed, reactive } from 'vue';
import { Close, ArrowUp, ArrowDown } from '@element-plus/icons-vue';
import VuePdfEmbed from "vue-pdf-embed";
import { createLoadingTask } from "vue3-pdfjs";const pdfFile = 'https://pic2-cdn.trytalks.com/pic2/202507091052/files_1a1b765ec00125e0FfuRNLZz.pdf?Expires=1754621583&OSSAccessKeyId=LTAI5tQd3SECCekgpXLBnQSo&Signature=nUn9kW375rdiVNHi2wdDLDm0gAM%3D'const state = reactive({source: pdfFile, // 預覽pdf文件地址pageNum: 1, // 當前頁面scale: 1, // 縮放比例numPages: 0, // 總頁數
});const loadingTask: any = ref(null)const pdfInit = () => {loadingTask.value = createLoadingTask(state.source);loadingTask.value.promise.then((pdf: { numPages: number }) => {state.numPages = pdf.numPages;});
}// 滾動到指定頁面
let isManualNavigation = false;
const scrollToPage = (page: number) => {// 設置手動導航標志isManualNavigation = true;// 先立即更新頁碼狀態const validPage = Math.max(1, Math.min(page, state.numPages));state.pageNum = validPage;// 執行滾動const element = document.getElementById(`pdf-page-${validPage}`);if (element) {element.scrollIntoView({behavior: 'smooth',block: 'start'});}// 滾動結束后清除標志setTimeout(() => {isManualNavigation = false;}, 1000);
};// 上一頁
const prevPage = (): void => {if (state.pageNum > 1) {scrollToPage(state.pageNum - 1);}
};// 下一頁
const nextPage = (): void => {const nextPage = state.pageNum + 1;if (nextPage <= state.numPages) {scrollToPage(nextPage);}
};// 跳轉到指定頁
const goToPage = (): void => {// 確保輸入是有效數字let page = parseInt(String(state.pageNum));if (isNaN(page) || page < 1) {page = 1;} else if (page > state.numPages) {page = state.numPages;}// 更新輸入框顯示正確的頁碼state.pageNum = page;scrollToPage(page);
};// 處理滾動事件,更新當前頁碼(帶防抖)
let scrollTimeout: number | null = null;
const handleScroll = () => {// 如果是手動導航觸發的滾動,則不更新頁碼if (isManualNavigation) return;if (scrollTimeout) {clearTimeout(scrollTimeout);}scrollTimeout = setTimeout(() => {const container = document.querySelector('.pdf-content');if (!container) return;const scrollPosition = container.scrollTop;const items = document.querySelectorAll('.pdf-item');const containerHeight = container.clientHeight;const threshold = containerHeight * 0.3; // 30%視口高度作為閾值let currentPage = state.pageNum;// 精確檢測當前可見頁面items.forEach((item) => {const pageNum = parseInt(item.id.replace('pdf-page-', ''));const rect = item.getBoundingClientRect();// 如果頁面頂部在視口閾值范圍內,則認為是當前頁if (rect.top >= -threshold && rect.top <= threshold) {currentPage = pageNum;}});// 只有當頁碼確實變化時才更新if (currentPage !== state.pageNum) {state.pageNum = currentPage;}}, 150) as unknown as number; // 適當增加防抖時間
};// 組件掛載時
onMounted(() => {// 檢查瀏覽器PDF支持const isPdfSupported = 'application/pdf' in navigator.mimeTypes;console.log('瀏覽器原生支持PDF:', isPdfSupported);// 添加滾動事件監聽const contentEl = document.querySelector('.pdf-content');if (contentEl) {contentEl.addEventListener('scroll', handleScroll);}pdfInit();
});onBeforeUnmount(() => {// 移除滾動事件監聽const contentEl = document.querySelector('.pdf-content');if (contentEl) {contentEl.removeEventListener('scroll', handleScroll);}
});
</script><style lang="scss" scoped>
.pdf-preview-container {display: flex;flex-direction: column;height: 100%;background-color: #fff;border-radius: 4px;overflow: hidden;.pdf-header {display: flex;justify-content: space-between;align-items: center;padding: 10px 16px;background-color: #fff;border-bottom: 1px solid #e0e0e0;.back-button {cursor: pointer;display: inline-block;padding: 5px 5px 0px;border-radius: 4px;transition: background-color 0.2s;&:hover {background-color: #f0f0f0;}}.pdf-actions {display: flex;gap: 10px;}.page-navigation {display: flex;align-items: center;.page-controls {display: flex;align-items: center;padding: 2px 8px;.page-input {width: 50px;margin: 0 5px;:deep(.el-input__inner) {text-align: center;padding: 0 5px;}}}.total-pages {margin-left: 5px;color: #606266;}}}.pdf-content {flex: 1;overflow: auto;/* 自定義滾動條樣式 */&::-webkit-scrollbar {width: 6px;height: 6px;}&::-webkit-scrollbar-track {background: rgba(0, 0, 0, 0.05);border-radius: 3px;}&::-webkit-scrollbar-thumb {background: rgba(0, 0, 0, 0.15);border-radius: 3px;transition: background 0.2s;&:hover {background: rgba(0, 0, 0, 0.25);}}.pdf-loading,.pdf-error {height: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;}.pdf-display-area {.pdf-item {margin: 16px 0px;}}}
}
</style>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/88538.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/88538.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/88538.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【AI論文】OmniPart:基于語義解耦與結構連貫性的部件感知三維生成

摘要&#xff1a;創建具有顯式、可編輯部件結構的三維資產&#xff0c;對于推動交互式應用的發展至關重要。然而&#xff0c;大多數生成方法僅能生成整體式形狀&#xff0c;限制了其實際應用價值。我們提出OmniPart——一種新型的部件感知三維物體生成框架&#xff0c;旨在實現…

Pandas-數據查看與質量檢查

Pandas-數據查看與質量檢查一、數據查看&#xff1a;快速掌握數據概況1. 整體概覽&#xff1a;shape與info()2. 數值特征預覽&#xff1a;describe()3. 隨機抽樣&#xff1a;head()與sample()二、數據質量檢查&#xff1a;識別與處理問題1. 缺失值檢查與處理處理策略&#xff1…

類和對象拓展——日期類

一.前言通過前面對類和對象的學習&#xff0c;現在我們可以開始實踐日期類的代碼編寫。在實際操作過程中&#xff0c;我會補充之前文章中未提及的相關知識點。二.正文 1. 日期類代碼實現我們先來看看要實現什么功能吧&#xff0c;把他放在Date.h中#pragma once #include<ios…

大模型KV緩存量化誤差補償機制:提升推理效率的關鍵技術

大模型KV緩存量化誤差補償機制&#xff1a;提升推理效率的關鍵技術摘要 隨著大型語言模型&#xff08;LLM&#xff09;參數規模突破千億級別&#xff0c;推理過程中的顯存占用與計算延遲成為制約其實際部署的核心瓶頸。KV緩存&#xff08;Key-Value Cache&#xff09;作為Trans…

QT跨平臺應用程序開發框架(6)—— 常用顯示類控件

目錄 一&#xff0c;Label 1.1 主要屬性 1.2 文本格式 1.3 設置圖片 1.4 其它常用屬性 1.5 設置伙伴 二&#xff0c;LCD Number 2.1 主要屬性 2.2 實現倒計時 ?2.3 兩個問題 三&#xff0c;ProgressBar 3.1 主要屬性 3.2 進度條按時間增長 3.3 改變樣式 3.4 一個問題 四&#…

LINUX文件系統權限,命令解釋器alias,文件查看和查找

1、文件査看:查看/etc/passwd文件的第5行[rootserver ~]# head -5 /etc/passwd | tail -1 #先找到前5行&#xff0c;用管道符過濾&#xff0c;顯示倒數第一行2、文件查找(1)在當前目錄及子目錄中&#xff0c;查找大寫字母開頭的txt文件[rootserver ~]# find / -name "[…

AI圖像修復工具CodeFormer實測:馬賽克去除與畫質增強效果評測

大家好&#xff01;平時看圖片或視頻&#xff0c;是不是特別煩人臉被馬賽克遮住的地方&#xff1f;比如老照片模糊、視頻關鍵部分被打碼&#xff0c;看著很不舒服。今天給大家分享一款超好用的去馬賽克神器——CodeFormer&#xff0c;完全免費&#xff0c;新手也能輕松搞定&…

知識宇宙-思考篇:AI大模型如何重塑軟件開發流程?

名人說&#xff1a;博觀而約取&#xff0c;厚積而薄發。——蘇軾《稼說送張琥》 創作者&#xff1a;Code_流蘇(CSDN)&#xff08;一個喜歡古詩詞和編程的Coder&#x1f60a;&#xff09; 目錄AI大模型重塑軟件開發&#xff1a;從碼農到AI編程伙伴的華麗轉身一、AI大模型的編程&…

Rocky Linux上使用NVM安裝Node.js 18

問題描述 Rocky Linux 9 默認 yum 安裝的 Node.js 版本是16&#xff0c;vite啟動報錯&#xff1a;TypeError: crypto$2.getRandomValues is not a function &#xff0c;需安裝更高版本的 Node.js 使用nvm安裝Node.js的好處 多版本管理&#xff0c;NVM 允許你安裝多個不同版本的…

JVM 中“對象存活判定方法”全面解析

1. 前言 在 Java 開發過程中&#xff0c;我們常常聽到“垃圾回收”&#xff08;Garbage Collection, GC&#xff09;這一術語。JVM 通過垃圾回收機制自動管理內存&#xff0c;極大地簡化了程序員的內存控制負擔。然而&#xff0c;GC 究竟是如何判斷哪些對象該回收、哪些應保留…

蘋果公司高ROE分析

公司通過增加負債提升凈資產收益率&#xff08;ROE&#xff09;的核心機制在于財務杠桿效應和資本結構優化&#xff0c;以下從原理、操作路徑、風險邊界及蘋果案例四維度展開分析&#xff1a;名稱解釋&#xff1a; ROIC(投入資本回報率)&#xff1a;ROICNOPATInvested Capital …

【Linux系統】進程概念

1. 進程概念1.1 進程的本質核心定義用戶視角&#xff1a;程序的動態執行實例&#xff08;如同時運行多個Chrome窗口即多個進程&#xff09;。內核視角&#xff1a;資源分配的最小實體單位&#xff0c;獨享CPU時間片、內存空間和文件資源。現代定義&#xff1a;進程 內核數據結…

從LLM到VLM:視覺語言模型的核心技術與Python實現

本教程的完整代碼可以在GitHub上找到&#xff0c;如果你有任何問題或建議&#xff0c;歡迎交流討論。 引言&#xff1a;為什么需要VLM&#xff1f; 當我們與ChatGPT對話時&#xff0c;它能夠理解復雜的文字描述&#xff0c;生成流暢的回答。但如果我們給它一張圖片&#xff0c…

老系統改造增加初始化,自動化數據源配置(tomcat+jsp+springmvc)

老系統改造增加初始化&#xff0c;自動化數據源配置一、前言二、改造描述1、環境說明2、實現步驟簡要思考三、開始改造1、準備sql初始化文件2、啟動時自動讀取jdbc文件&#xff0c;創建數據源&#xff0c;如未配置&#xff0c;需要一個默認的臨時數據源2.1去掉sping mvc原本配置…

衛星通信終端天線的5種對星模式之二:DVB跟蹤

要實現穩定可靠的衛星通信&#xff0c;地面終端天線必須精準地對準遠方的衛星。對星的過程是一個不斷搜索、不斷逼近的過程&#xff0c;其目標是讓天線波束中心精確指向衛星&#xff0c;從而獲得最大信號接收與發射效率。 衛星通信終端天線的對星技術是保障衛星通信鏈路穩定的…

重構下一代智能電池“神經中樞”:GCKontrol定義高性能BMS系統級設計標桿

概述BMS&#xff08;電池管理系統&#xff09;作為新能源汽車動力電池與整車的核心紐帶&#xff0c;通過實時監控電壓、電流、溫度及SOC等參數&#xff0c;控制電池充放電過程&#xff0c;保障電池安全性與使用壽命。隨著電動汽車智能化發展&#xff0c;對BMS的響應速度、精度和…

面試150 對稱二叉樹

思路 聯想遞歸三部曲&#xff1a;傳入參數、遍歷方式、返回什么。本題聯想到先序遍歷的方式,需要遍歷整顆二叉樹,最后返回的是一個布爾值。然后我們需要傳入的是左子樹和左子樹的節點,然后分別進行比較。 # Definition for a binary tree node. # class TreeNode: # def __…

多線程的區別和聯系

進程和線程的區別和聯系1.一個進程可以包含多個線程&#xff0c;不能夠沒有線程2.進程是系統資源分配的基本單位&#xff0c;線程是系統調度執行的基本單位3.同一個進程里的線程之間&#xff0c;共用同一份系統資源4.線程是當下實現并發編程的主流方式&#xff0c;通過多線程&a…

兩個文件夾自動同步

兩個文件夾自動同步&#xff0c;非常簡單&#xff0c;利用一些工具就可以輕松做到&#xff0c;設置完源和目標文件夾&#xff0c;點擊啟動就馬上可以兩個文件夾自動同步&#xff0c;對于一些有文件同步、文件災備需求的老登&#xff0c;用起來會非常順手&#xff0c;比如PanguF…

虛擬商品交易維權指南:數字經濟時代的消費者權益保護

首席數據官高鵬律師數字經濟團隊創作AI輔助在元宇宙、NFT、虛擬情緒產品等新興領域蓬勃發展的今天&#xff0c;虛擬商品交易已成為數字經濟的重要組成部分。從游戲皮膚、在線課程到數字藏品&#xff0c;消費者在享受虛擬商品便捷性的同時&#xff0c;也面臨著諸多法律風險。作為…