Vue3+TypeScript项目中安装PDF.js详细的步骤
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li><a href="#_label0">1. 安装 pdfjs-dist</a></li><li><a href="#_label1">2. 安装类型声明文件(TypeScript 支持)</a></li><li><a href="#_label2">3. 基础使用示例</a></li><ul class="second_class_ul"><li><a href="#_lab2_2_0">选项 1:直接使用(简单场景)</a></li><li><a href="#_lab2_2_1">选项 2:使用 Worker(推荐用于生产)</a></li></ul><li><a href="#_label3">4. 创建可复用的 PDF 查看器组件</a></li><ul class="second_class_ul"><li><a href="#_lab2_3_2">PDFViewer.vue</a></li></ul><li><a href="#_label4">5. 使用组件</a></li><ul class="second_class_ul"></ul><li><a href="#_label5">注意事项</a></li><ul class="second_class_ul"></ul><li><a href="#_label6">总结</a></li><ul class="second_class_ul"></ul></ul></div><p>在 Vue 3 + TypeScript 项目中安装和使用 pdfjs-dist(PDF.js),以下是详细的步骤:</p><p class="maodian"><a name="_label0"></a></p><h2>1. 安装 pdfjs-dist</h2>
<p>bash</p>
<div class="jb51code"><pre class="brush:ps;">npm install pdfjs-dist
# 或者
yarn add pdfjs-dist
# 或者
pnpm add pdfjs-dist</pre></div>
<p class="maodian"><a name="_label1"></a></p><h2>2. 安装类型声明文件(TypeScript 支持)</h2>
<p>bash</p>
<div class="jb51code"><pre class="brush:ps;">npm install @types/pdfjs-dist
# 或(新版本可能需要)
npm install --save-dev @types/pdfjs-dist</pre></div>
<p class="maodian"><a name="_label2"></a></p><h2>3. 基础使用示例</h2>
<p class="maodian"><a name="_lab2_2_0"></a></p><h3>选项 1:直接使用(简单场景)</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;"><template>
<div>
<canvas ref="canvasRef"></canvas>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
// 设置 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`
const canvasRef = ref<HTMLCanvasElement | null>(null)
onMounted(async () => {
// 加载 PDF
const loadingTask = pdfjsLib.getDocument('/path/to/your.pdf')
const pdf = await loadingTask.promise
// 获取第一页
const page = await pdf.getPage(1)
// 设置缩放
const scale = 1.5
const viewport = page.getViewport({ scale })
// 渲染到 canvas
const canvas = canvasRef.value
if (!canvas) return
const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
const renderContext = {
canvasContext: context,
viewport: viewport
}
await page.render(renderContext).promise
})
</script></pre></div>
<p class="maodian"><a name="_lab2_2_1"></a></p><h3>选项 2:使用 Worker(推荐用于生产)</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;"><template>
<div>
<canvas ref="canvasRef"></canvas>
<div v-if="pageCount">总页数: {{ pageCount }}</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import type { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'
// 使用 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`
// 或者使用本地 worker
// pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
// 'pdfjs-dist/build/pdf.worker.min.js',
// import.meta.url
// ).toString()
const canvasRef = ref<HTMLCanvasElement | null>(null)
const pageCount = ref<number>(0)
// 渲染 PDF 页面
const renderPage = async (pdf: PDFDocumentProxy, pageNum: number) => {
const page = await pdf.getPage(pageNum)
const scale = 1.5
const viewport = page.getViewport({ scale })
const canvas = canvasRef.value
if (!canvas) return
const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
const renderContext = {
canvasContext: context,
viewport: viewport
}
await page.render(renderContext).promise
}
// 加载 PDF
const loadPDF = async (url: string) => {
try {
const loadingTask = pdfjsLib.getDocument(url)
const pdf = await loadingTask.promise
pageCount.value = pdf.numPages
await renderPage(pdf, 1)
return pdf
} catch (error) {
console.error('Error loading PDF:', error)
throw error
}
}
onMounted(() => {
// 加载 PDF
loadPDF('/path/to/your.pdf')
})
</script></pre></div>
<p class="maodian"><a name="_label3"></a></p><h2>4. 创建可复用的 PDF 查看器组件</h2>
<p class="maodian"><a name="_lab2_3_2"></a></p><h3>PDFViewer.vue</h3>
<p>vue</p>
<div class="jb51code"><pre class="brush:js;"><template>
<div class="pdf-viewer">
<div class="toolbar">
<button @click="prevPage" :disabled="currentPage <= 1">上一页</button>
<span>第 {{ currentPage }} 页 / 共 {{ totalPages }} 页</span>
<button @click="nextPage" :disabled="currentPage >= totalPages">下一页</button>
<input
type="number"
v-model.number="inputPage"
@change="goToPage"
min="1"
:max="totalPages"
>
<button @click="zoomIn">放大</button>
<button @click="zoomOut">缩小</button>
</div>
<div class="pdf-container">
<canvas ref="canvasRef"></canvas>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import type { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'
interface Props {
src: string
}
const props = defineProps<Props>()
const canvasRef = ref<HTMLCanvasElement | null>(null)
const currentPage = ref(1)
const totalPages = ref(0)
const inputPage = ref(1)
const scale = ref(1.5)
let pdfInstance: PDFDocumentProxy | null = null
// 配置 worker
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`
// 渲染当前页
const renderCurrentPage = async () => {
if (!pdfInstance || !canvasRef.value) return
const page = await pdfInstance.getPage(currentPage.value)
const viewport = page.getViewport({ scale: scale.value })
const canvas = canvasRef.value
const context = canvas.getContext('2d')
canvas.height = viewport.height
canvas.width = viewport.width
const renderContext = {
canvasContext: context,
viewport: viewport
}
await page.render(renderContext).promise
}
// 加载 PDF
const loadPDF = async () => {
try {
const loadingTask = pdfjsLib.getDocument(props.src)
pdfInstance = await loadingTask.promise
totalPages.value = pdfInstance.numPages
currentPage.value = 1
inputPage.value = 1
await renderCurrentPage()
} catch (error) {
console.error('Failed to load PDF:', error)
}
}
// 导航方法
const prevPage = () => {
if (currentPage.value > 1) {
currentPage.value--
inputPage.value = currentPage.value
}
}
const nextPage = () => {
if (pdfInstance && currentPage.value < pdfInstance.numPages) {
currentPage.value++
inputPage.value = currentPage.value
}
}
const goToPage = () => {
if (pdfInstance) {
const pageNum = Math.max(1, Math.min(inputPage.value, pdfInstance.numPages))
currentPage.value = pageNum
inputPage.value = pageNum
}
}
const zoomIn = () => {
scale.value += 0.25
}
const zoomOut = () => {
scale.value = Math.max(0.5, scale.value - 0.25)
}
// 监听页面变化
watch(currentPage, renderCurrentPage)
watch(scale, renderCurrentPage)
// 监听 PDF 源变化
watch(() => props.src, loadPDF)
onMounted(loadPDF)
</script>
<style scoped>
.pdf-viewer {
width: 100%;
height: 100%;
}
.toolbar {
display: flex;
gap: 10px;
padding: 10px;
background: #f5f5f5;
align-items: center;
}
.pdf-container {
overflow: auto;
padding: 20px;
}
canvas {
border: 1px solid #ddd;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
</style></pre></div>
<p class="maodian"><a name="_label4"></a></p><h2>5. 使用组件</h2>
<p>vue</p>
<div class="jb51code"><pre class="brush:xhtml;"><template>
<div>
<PDFViewer src="/path/to/document.pdf" />
</div>
</template>
<script setup lang="ts">
import PDFViewer from './components/PDFViewer.vue'
</script></pre></div>
<p class="maodian"><a name="_label5"></a></p><h2>注意事项</h2>
<ul><li><p><strong>Worker 配置</strong>:生产环境中建议使用 worker 提高性能</p></li><li><p><strong>版本兼容性</strong>:确保 pdfjs-dist 和 @types/pdfjs-dist 版本兼容</p></li><li><p><strong>CDN 或本地</strong>:可以选择使用 CDN 或本地 worker 文件</p></li><li><p><strong>内存管理</strong>:大型 PDF 注意内存管理,及时清理资源</p></li><li><p><strong>错误处理</strong>:添加适当的错误处理机制</p></li></ul>
<p>这样你就可以在 Vue 3 + TypeScript 项目中成功使用 PDF.js 了!</p>
<p class="maodian"><a name="_label6"></a></p><h2>总结</h2>
頁:
[1]