| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- <template>
- <div class="home_wrap">
- <div class="pdf_down">
- <div class="pdf_set_left" @click="scaleD">➕</div>
- <div class="pdf_set_middle" @click="scaleX">➖</div>
- <!-- <div class="pdf-pre" @click="prePage">上一页</div> -->
- <!-- <div class="pdf-next" @click="nextPage">下一页</div> -->
- </div>
- <div :style="{ width: pdf_div_width, margin: '0 auto' }">
- <!-- <canvas id="the_canvas"></canvas> -->
- <canvas
- v-for="page in pdf_pages"
- :id="'the_canvas' + page"
- :key="page"
- ></canvas>
- </div>
- </div>
- </template>
- <script setup>
- import { ref, onMounted } from "vue"
- import * as PDF from "pdfjs-dist"
- // 引入 Vite 识别的 worker URL(处理哈希路径)
- import localWorkerUrl from "pdfjs-dist/build/pdf.worker.mjs?url"
- let workerBlobUrl = null
- const initWorker = async () => {
- if (workerBlobUrl) return
- const pdfjsVersion = PDF.version
- const urls = [
- // 1. 优先使用 CDN,规避所有本地服务器配置问题
- `https://cdn.jsdelivr.net/npm/pdfjs-dist@${pdfjsVersion}/build/pdf.worker.min.mjs`,
- `https://unpkg.com/pdfjs-dist@${pdfjsVersion}/build/pdf.worker.min.mjs`,
- // 2. 本地备选:Vite 处理后的路径
- localWorkerUrl,
- // 3. 库模式下的路径
- new URL("./pdf.worker.js", import.meta.url).toString(),
- ]
- let lastError = null
- for (const url of urls) {
- try {
- const response = await fetch(url)
- if (!response.ok) continue
- const arrayBuffer = await response.arrayBuffer()
- // 强制指定为 ESM 模块
- const blob = new Blob([arrayBuffer], { type: "text/javascript" })
- workerBlobUrl = URL.createObjectURL(blob)
- PDF.GlobalWorkerOptions.workerSrc = workerBlobUrl
- console.log("PDF Worker loaded successfully from:", url)
- return
- } catch (e) {
- lastError = e
- continue
- }
- }
- console.error("All PDF worker paths failed", lastError)
- // 最后保底:直接尝试 localWorkerUrl
- PDF.GlobalWorkerOptions.workerSrc = localWorkerUrl
- }
- const props = defineProps({
- data: Array,
- })
- const pdf_scale = ref(1.0)
- const pdf_pages = ref([])
- const pdf_div_width = ref("")
- const currentPage = ref(1)
- let pdfDoc = null
- const scaleD = () => {
- let max = 0
- if (window.screen.width > 1440) {
- max = 1.4
- } else {
- max = 1.2
- }
- if (pdf_scale.value >= max) {
- return
- }
- pdf_scale.value = pdf_scale.value + 0.1
- loadFile()
- }
- const scaleX = () => {
- let min = 1.0
- if (pdf_scale.value <= min) {
- return
- }
- pdf_scale.value = pdf_scale.value - 0.1
- loadFile()
- }
- const loadFile = async () => {
- await initWorker()
- pdfDoc = await PDF.getDocument(props.data).promise
- pdf_pages.value = pdfDoc.numPages
- renderPage()
- }
- const renderPage = async (num = 1) => {
- currentPage.value = num
- const page = await pdfDoc.getPage(num)
- const canvas = document.getElementById("the_canvas" + num)
- const ctx = canvas.getContext("2d")
- const dpr = window.devicePixelRatio || 1
- const bsr =
- ctx.webkitBackingStorePixelRatio ||
- ctx.mozBackingStorePixelRatio ||
- ctx.msBackingStorePixelRatio ||
- ctx.oBackingStorePixelRatio ||
- ctx.backingStorePixelRatio ||
- 1
- const ratio = dpr / bsr
- const viewport = page.getViewport({ scale: pdf_scale.value })
- canvas.width = viewport.width * ratio
- canvas.height = viewport.height * ratio
- canvas.style.width = viewport.width + "px"
- pdf_div_width.value = viewport.width + "px"
- canvas.style.height = viewport.height + "px"
- ctx.setTransform(ratio, 0, 0, ratio, 0, 0)
- const renderContext = {
- canvasContext: ctx,
- viewport: viewport,
- }
- page.render(renderContext)
- if (pdf_pages.value > num) {
- setTimeout(() => {
- return renderPage(num + 1)
- })
- }
- }
- const nextPage = () => {
- if (pdf_pages.value > currentPage.value) {
- renderPage(currentPage.value + 1)
- }
- }
- const prePage = () => {
- if (currentPage.value > 1) {
- renderPage(currentPage.value - 1)
- }
- }
- onMounted(() => {
- loadFile()
- })
- </script>
- <style scoped>
- .home_wrap {
- width: 100%;
- height: 100%;
- }
- .home_wrap .pdf_down {
- position: fixed;
- display: flex;
- z-index: 20;
- right: 26px;
- bottom: 7%;
- cursor: pointer;
- }
- .home_wrap .pdf-pre {
- position: fixed;
- display: flex;
- z-index: 20;
- right: 160px;
- bottom: 9%;
- cursor: pointer;
- }
- .home_wrap .pdf-next {
- position: fixed;
- display: flex;
- z-index: 20;
- right: 100px;
- bottom: 9%;
- }
- .home_wrap .pdf_down .pdf_set_left {
- width: 30px;
- height: 40px;
- color: #408fff;
- font-size: 15px;
- padding-top: 25px;
- text-align: center;
- margin-right: 5px;
- cursor: pointer;
- }
- .home_wrap .pdf_down .pdf_set_middle {
- width: 30px;
- height: 40px;
- color: #408fff;
- font-size: 15px;
- padding-top: 25px;
- text-align: center;
- margin-right: 5px;
- cursor: pointer;
- }
- </style>
|