vue3 实现pdf预览及点击图片列表显示隐藏对应的图片
我这边简单,只是显示pdf文件,然后点击图片切换对应的图片。然后下载的时候能下载出来即可
上代码,装依赖
cnpm install pdf-lib pdfjs-dist file-saver
下面是业务代码
<template> <div> <!-- 控制面板:选择要嵌入到PDF的图片 --> <div class="controls"> <h3> 选择要嵌入到PDF的图片:<button class="download-button" @click="downloadModifiedPDF"> 下载包含选中图片的PDF </button> </h3> <div class="image-options"> <!-- 遍历图片列表,显示每个图片的名称和选中状态 --> <label v-for="(image, index) in images" :key="image.id"> <span @click="imageClick(index)" style="cursor: pointer"> {{ image.name }} {{ image.checked ? '✔' : '' }} </span> </label> </div> </div> <!-- PDF预览区域 --> <div class="container"> <div class="pdf-container" id="original-pdf-viewer"> <h2>原始PDF 文件:</h2> <!-- 使用iframe嵌入原始PDF,并隐藏工具栏和菜单栏 --> <iframe id="original-pdf-iframe" :src="pdfUrl" width="100%" height="550px" style="border: none"></iframe> </div> <div class="modified-pdf-container" id="modified-pdf-viewer"> <h2>修改后的PDF 预览:</h2> <!-- 使用iframe嵌入修改后的PDF --> <iframe id="modified-pdf-iframe" :src="modifiedPdfUrl" width="100%" height="550px" style="border: none" ></iframe> </div> </div> <!-- 显示选中的图片 --> <div class="images-container"> <img v-for="image in images" :key="image.id" :src="image.src" :id="image.id" v-show="image.checked" style="max-width: 150px; margin: 10px; display: inline-block" /> </div> </div> </template> <script setup> import { ref } from 'vue' import { PDFDocument } from 'pdf-lib' import { saveAs } from 'file-saver' // #toolbar=0:隐藏工具栏。 // #menubar=0:隐藏菜单栏。 // #scrollbar=0:隐藏滚动条。 // #navpanes=0:隐藏导航窗格(缩略图等)。 // PDF URL和修改后的PDF URL const pdfUrl = ref('你pdf文件#toolbar=0') const modifiedPdfUrl = ref('') // 图片列表 const images = ref([ { id: 'img1', name: '左侧部分图片', src: '要展示的文件地址', checked: false }, { id: 'img2', name: '右侧部分图片', src: '要展示的文件地址', checked: false }, { id: 'img3', name: '检测专用章', src: '要展示的文件地址', checked: false } // ...其他图片 ]) // 预览修改后的PDF const previewModifiedPDF = async () => { // 获取选中的图片 const selectedImages = images.value.filter((image) => image.checked) if (selectedImages.length === 0) { alert('请选择至少一张图片来嵌入到PDF中。') return } try { // 加载原始PDF const response = await fetch(pdfUrl.value) const existingPdfBytes = await response.arrayBuffer() const pdfDoc = await PDFDocument.load(existingPdfBytes) // 获取第一页 const firstPage = pdfDoc.getPages()[0] // 图片位置配置 const imagePositions = { img1: { x: 37, y: firstPage.getHeight() - 150, width: 70, height: 50 }, img2: { x: firstPage.getWidth() - 100, y: firstPage.getHeight() - 150, width: 70, height: 50 }, img3: { x: 80, y: firstPage.getHeight() / 2 - 210, width: 70, height: 70 } // img3: { x: firstPage.getWidth() / 2 - 50, y: firstPage.getHeight() - 150, width: 100, height: 100 } } // 遍历选中的图片并嵌入到PDF for (const imgSrc of selectedImages) { const imgResponse = await fetch(imgSrc.src) const imgBytes = await imgResponse.arrayBuffer() let img // 根据图片格式嵌入图片 if (imgSrc.src.toLowerCase().endsWith('.jpg') || imgSrc.src.toLowerCase().endsWith('.jpeg')) { img = await pdfDoc.embedJpg(imgBytes) } else if (imgSrc.src.toLowerCase().endsWith('.png')) { img = await pdfDoc.embedPng(imgBytes) } else { alert(`不支持的图片格式:${imgSrc.src}`) continue } // 在PDF上绘制图片 const pos = imagePositions[imgSrc.id] firstPage.drawImage(img, { x: pos.x, y: pos.y, width: pos.width, height: pos.height }) } // 保存修改后的PDF并生成预览URL const modifiedPdfBytes = await pdfDoc.save() modifiedPdfUrl.value = URL.createObjectURL(new Blob([modifiedPdfBytes], { type: 'application/pdf' })) + '#toolbar=0' } catch (error) { console.log('预览修改后的PDF时出错:', error) alert('在预览PDF时发生错误。请检查控制台获取更多信息。') } } // 下载修改后的PDF const downloadModifiedPDF = () => { if (!modifiedPdfUrl.value) { alert('请先点击“预览”按钮生成修改后的PDF。') return } try { saveAs(modifiedPdfUrl.value, 'modified_10086.pdf') } catch (error) { console.log('下载修改后的PDF时出错:', error) alert('在下载PDF时发生错误。请检查控制台获取更多信息。') } } // 切换图片选中状态 const imageClick = (index) => { images.value[index].checked = !images.value[index].checked // 如果有选中的图片,则预览修改后的PDF if (images.value.filter((item) => item.checked).length > 0) previewModifiedPDF() } </script> <style> body { font-family: Arial, sans-serif; margin: 20px; } .controls { margin-bottom: 20px; } .controls label { display: block; margin: 5px 0; } .container { display: flex; gap: 40px; } .pdf-container, .modified-pdf-container { border: 1px solid #ccc; width: 45%; height: 630px; overflow: auto; } .download-button, .preview-button { padding: 5px; font-size: 12px; } .image-options { width: 60%; display: flex; justify-content: space-between; } .images-container { display: none; /* 初始隐藏 */ margin-top: 20px; } .images-container img { max-width: 150px; margin: 10px; display: none; /* 初始隐藏 */ } </style>