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>

浙公网安备 33010602011771号