vue3: pdf.js 2.16.105 using typescript

news2025/7/17 8:17:58
npm create vite vuepdfpreview  //创建项目
 
npm install vue-pdf-embed
npm install vue3-pdfjs
npm install pdfjs-dist@2.16.105 
<!--
 *                                |~~~~~~~|
 *                                |       |
 *                                |       |
 *                                |       |
 *                                |       |
 *                                |       |
 *     |~.\\\_\~~~~~~~~~~~~~~xx~~~         ~~~~~~~~~~~~~~~~~~~~~/_//;~|
 *     |  \  o \_         ,XXXXX),                         _..-~ o /  |
 *     |    ~~\  ~-.     XXXXX`)))),                 _.--~~   .-~~~   |
 *      ~~~~~~~`\   ~\~~~XXX' _/ ';))     |~~~~~~..-~     _.-~ ~~~~~~~
 *               `\   ~~--`_\~\, ;;;\)__.---.~~~      _.-~
 *                 ~-.       `:;;/;; \          _..-~~
 *                    ~-._      `''        /-~-~
 *                        `\              /  /
 *                          |         ,   | |
 *                           |  '        /  |
 *                            \/;          |
 *                             ;;          |
 *                             `;   .       |
 *                             |~~~-----.....|
 *                            | \             \
 *                           | /\~~--...__    |
 *                           (|  `\       __-\|
 *                           ||    \_   /~    |
 *                           |)     \~-'      |
 *                            |      | \      '
 *                            |      |  \    :
 *                             \     |  |    |
 *                              |    )  (    )
 *                               \  /;  /\  |
 *                               |    |/   |
 *                               |    |   |
 *                                \  .'  ||
 *                                |  |  | |
 *                                (  | |  |
 *                                |   \ \ |
 *                                || o `.)|
 *                                |`\\) |
 *                                |       |
 *                                |       |
 *
 * @Author: geovindu
 * @Date: 2025-05-08 20:54:24
 * @LastEditors: geovindu
 * @LastEditTime: 2025-05-08 22:22:28
 * @FilePath: \vue\vuepdfpreview\src\App.vue
 * @Description: geovindu
 * @lib,packpage:
 * npm install vue-pdf-embed
 * npm install vue3-pdfjs
 *  npm install pdfjs-dist@2.16.105
 * @IDE: vscode
 * @jslib: node 20 vue.js 3.0
 * @OS: windows10
 * @database: mysql 8.0  sql server 2019 postgreSQL 16
 * Copyright (c) geovindu 2025 by geovindu@163.com, All Rights Reserved.
 -->
 
 
 
<template>
<div class="pdf-container">
    <PDFView :pdfUrl="pdfUrl" v-if="pdfUrl" />
    <div v-else >加载中...</div>
  <div>
    <a href="https://vite.dev" target="_blank">
      <img src="/vite.svg" class="logo" alt="Vite logo" />
    </a>
    <a href="https://vuejs.org/" target="_blank">
      <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
    </a>
  </div>
  <HelloWorld msg="Vite + Vue" />
 </div>
 </template>
 <script setup lang="ts">
 
 import HelloWorld from './components/HelloWorld.vue'
 //import PDFView from "./components/pdfPreview.vue" // 可以
 import PDFView from "./components/pdfjs.vue"   //可以
 //import jsPdf from "http://localhost:5173/pdfs/01.pdf"
 const pdfUrl = "./pdfs/09.pdf"
 </script>
 
  
<style scoped>
.logo {
  height: 6em;
  padding: 1.5em;
  will-change: filter;
  transition: filter 300ms;
}
.logo:hover {
  filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.vue:hover {
  filter: drop-shadow(0 0 2em #42b883aa);
}
</style>
<!--
 *                        ::
 *                       :;J7, :,                        ::;7:
 *                       ,ivYi, ,                       ;LLLFS:
 *                       :iv7Yi                       :7ri;j5PL
 *                      ,:ivYLvr                    ,ivrrirrY2X,
 *                      :;r@Wwz.7r:                :ivu@kexianli.
 *                     :iL7::,:::iiirii:ii;::::,,irvF7rvvLujL7ur
 *                    ri::,:,::i:iiiiiii:i:irrv177JX7rYXqZEkvv17
 *                 ;i:, , ::::iirrririi:i:::iiir2XXvii;L8OGJr71i
 *               :,, ,,:   ,::ir@mingyi.irii:i:::j1jri7ZBOS7ivv,
 *                  ,::,    ::rv77iiiriii:iii:i::,rvLq@huhao.Li
 *              ,,      ,, ,:ir7ir::,:::i;ir:::i:i::rSGGYri712:
 *            :::  ,v7r:: ::rrv77:, ,, ,:i7rrii:::::, ir7ri7Lri
 *           ,     2OBBOi,iiir;r::        ,irriiii::,, ,iv7Luur:
 *         ,,     i78MBBi,:,:::,:,  :7FSL: ,iriii:::i::,,:rLqXv::
 *         :      iuMMP: :,:::,:ii;2GY7OBB0viiii:i:iii:i:::iJqL;::
 *        ,     ::::i   ,,,,, ::LuBBu BBBBBErii:i:i:i:i:i:i:r77ii
 *       ,       :       , ,,:::rruBZ1MBBqi, :,,,:::,::::::iiriri:
 *      ,               ,,,,::::i:  @arqiao.       ,:,, ,:::ii;i7:
 *     :,       rjujLYLi   ,,:::::,:::::::::,,   ,:i,:,,,,,::i:iii
 *     ::      BBBBBBBBB0,    ,,::: , ,:::::: ,      ,,,, ,,:::::::
 *     i,  ,  ,8BMMBBBBBBi     ,,:,,     ,,, , ,   , , , :,::ii::i::
 *     :      iZMOMOMBBM2::::::::::,,,,     ,,,,,,:,,,::::i:irr:i:::,
 *     i   ,,:;u0MBMOG1L:::i::::::  ,,,::,   ,,, ::::::i:i:iirii:i:i:
 *     :    ,iuUuuXUkFu7i:iii:i:::, :,:,: ::::::::i:i:::::iirr7iiri::
 *     :     :rk@Yizero.i:::::, ,:ii:::::::i:::::i::,::::iirrriiiri::,
 *      :      5BMBBBBBBSr:,::rv2kuii:::iii::,:i:,, , ,,:,:i@petermu.,
 *           , :r50EZ8MBBBBGOBBBZP7::::i::,:::::,: :,:,::i;rrririiii::
 *               :jujYY7LS0ujJL7r::,::i::,::::::::::::::iirirrrrrrr:ii:
 *            ,:  :@kevensun.:,:,,,::::i:i:::::,,::::::iir;ii;7v77;ii;i,
 *            ,,,     ,,:,::::::i:iiiii:i::::,, ::::iiiir@xingjief.r;7:i,
 *         , , ,,,:,,::::::::iiiiiiiiii:,:,:::::::::iiir;ri7vL77rrirri::
 *          :,, , ::::::::i:::i:::i:i::,,,,,:,::i:i:::iir;@Secbone.ii:::
 *
 * @Author: geovindu
 * @Date: 2025-05-08 21:00:52
 * @LastEditors: geovindu
 * @LastEditTime: 2025-05-08 22:47:03
 * @FilePath: \vue\vuepdfpreview\src\components\pdfjs.vue
 * @Description: geovindu
 * @lib,packpage:
 *
 * @IDE: vscode
 * @jslib: node 20 vue.js 3.0
 * @OS: windows10
 * @database: mysql 8.0  sql server 2019 postgreSQL 16
 * Copyright (c) geovindu 2025 by geovindu@163.com, All Rights Reserved.
 -->
<template>
    <div class="pdf-container">
      <div v-if="loading" class="text-center py-8">加载中...</div>
      <div v-else-if="error" class="text-center py-8 text-red-500">{{ error }}</div>
      <div v-else>
        <div class="flex justify-between items-center mb-4">
          <div class="flex space-x-2">
            <button @click="zoomIn" class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600">放大</button>
            <button @click="zoomOut" class="px-3 py-1 bg-blue-500 text-white rounded hover:bg-blue-600">缩小</button>
            <button @click="downloadPDF" class="px-3 py-1 bg-green-500 text-white rounded hover:bg-green-600">下载文档</button>
          </div>
          <div class="text-center">
            第 {{ currentPage }} / {{ totalPages }} 页
            <button @click="prevPage" :disabled="currentPage <= 1" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">上一页</button>
            <button @click="nextPage" :disabled="currentPage >= totalPages" class="px-3 py-1 bg-gray-200 rounded hover:bg-gray-300">下一页</button>
          </div>
        </div>
        <div id="pdf-container" class="w-full h-[600px] border border-gray-300 overflow-auto">
          <canvas ref="pdfCanvas"></canvas>
        </div>
      </div>
    </div>
  </template>
   
  <script setup>
  import { ref, onMounted, reactive } from 'vue';
  import * as pdfjsLib from 'pdfjs-dist';
   
  // 设置 worker 路径
  pdfjsLib.GlobalWorkerOptions.workerSrc = '/pdfjs/pdf.worker.js';
   
  const props = defineProps({
    pdfUrl: { type: String, required: true }
  });
   
  const pdfCanvas = ref(null);
  const loading = ref(true);
  const error = ref('');
  const currentPage = ref(1);
  const totalPages = ref(0);
  const scale = ref(1.0);
  let pdfDoc = null;
   
  const renderPage = async (num) => {
    try {
      const page = await pdfDoc.getPage(num);
      const viewport = page.getViewport({ scale: scale.value });
   
      // 设置 canvas 尺寸
      pdfCanvas.value.width = viewport.width;
      pdfCanvas.value.height = viewport.height;
   
      // 渲染页面
      const renderContext = {
        canvasContext: pdfCanvas.value.getContext('2d'),
        viewport: viewport
      };
   
      await page.render(renderContext).promise;
      currentPage.value = num;
    } catch (err) {
      console.error('渲染页面失败:', err);
      error.value = `渲染失败: ${err.message}`;
    }
  };
   
  const prevPage = () => {
    if (currentPage.value > 1) {
      renderPage(currentPage.value - 1);
    }
  };
   
  const nextPage = () => {
    if (currentPage.value < totalPages.value) {
      renderPage(currentPage.value + 1);
    }
  };
   
  const zoomIn = () => {
    scale.value += 0.1;
    renderPage(currentPage.value);
  };
   
  const zoomOut = () => {
    if (scale.value > 0.2) {
      scale.value -= 0.1;
      renderPage(currentPage.value);
    }
  };
   
  const downloadPDF = () => {
    const link = document.createElement('a');
    link.href = props.pdfUrl;
    link.download = props.pdfUrl.split('/').pop();
    link.click();
  };
   
  onMounted(async () => {
    try {
      // 加载 PDF
      const loadingTask = pdfjsLib.getDocument(props.pdfUrl);
      pdfDoc = await loadingTask.promise;
      totalPages.value = pdfDoc.numPages;
   
      // 渲染第一页
      renderPage(1);
      loading.value = false;
    } catch (err) {
      console.error('加载 PDF 失败:', err);
      error.value = `加载失败: ${err.message}`;
      loading.value = false;
    }
  });
  </script>
   
  <style scoped>
  .pdf-container {
    max-width: 1000px;
    margin: 0 auto;
  }
   
  #pdf-container canvas {
    max-width: 100%;
    display: block;
    margin: 0 auto;
  }
  </style>

onMounted(async () => {
  try {
    // 假设props.pdfUrl现在是Base64编码的PDF字符串
    // 移除可能存在的Data URI前缀(如"data:application/pdf;base64,")
    const base64Data = props.pdfUrl.replace(/^data:application\/pdf;base64,/, '');
    
    // 将Base64字符串转换为Uint8Array
    const binaryData = atob(base64Data);
    const arrayBuffer = new ArrayBuffer(binaryData.length);
    const uint8Array = new Uint8Array(arrayBuffer);
    
    for (let i = 0; i < binaryData.length; i++) {
      uint8Array[i] = binaryData.charCodeAt(i);
    }
    
    // 使用Uint8Array加载PDF
    const loadingTask = pdfjsLib.getDocument({ data: uint8Array });
    pdfDoc = await loadingTask.promise;
    totalPages.value = pdfDoc.numPages;
    
    // 渲染第一页
    renderPage(1);
    loading.value = false;
  } catch (err) {
    console.error('加载PDF失败:', err);
    error.value = `加载失败: ${err.message}`;
    loading.value = false;
  }
});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2372616.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从 MDM 到 Data Fabric:下一代数据架构如何释放 AI 潜能

从 MDM 到 Data Fabric&#xff1a;下一代数据架构如何释放 AI 潜能 —— 传统治理与新兴架构的范式变革与协同进化 引言&#xff1a;AI 规模化落地的数据困境 在人工智能技术快速发展的今天&#xff0c;企业对 AI 的期望已从 “单点实验” 转向 “规模化落地”。然而&#…

【软件测试】测试用例的设计方法

目录 一、基于需求进行测试用例的设计 1.1 功能需求测试分析 二、黑盒测试用例设计方法 2.1 等价类划分法(解决穷举) 2.1.1 等价类设计步骤 2.1.2 等价类划分法案例 2.1.2.1 验证 QQ 账号的合法性 2.1.2.2 验证某城市电话号码的正确性 2.1.3 适用场景 2.2 边界值分析…

GStreamer开发笔记(三):测试gstreamer/v4l2+sdl2/v4l2+QtOpengl打摄像头延迟和内存

若该文为原创文章&#xff0c;转载请注明原文出处 本文章博客地址&#xff1a;https://blog.csdn.net/qq21497936/article/details/147714800 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、O…

科技成果鉴定测试有哪些内容?又有什么作用?

科技成果鉴定测试是评价科技成果质量和水平的方法之一&#xff0c;通过测试&#xff0c;可以对科技成果的技术优劣进行评估&#xff0c;从而为科技创新提供参考和指导。 一、科技成果鉴定测试的内容   1.技术评审&#xff1a;通过技术专家对项目进行详细的技术分析&#xff…

基于Spring Boot + Vue 项目中引入deepseek方法

准备工作 在开始调用 DeepSeek API 之前&#xff0c;你需要完成以下准备工作&#xff1a; 1.访问 DeepSeek 官网&#xff0c;注册一个账号。 2.获取 API 密钥&#xff1a;登录 DeepSeek 平台&#xff0c;进入 API 管理 页面。创建一个新的 API 密钥&#xff08;API Key&#x…

A2A与MCP定义下,User,Agent,api(tool)间的交互流程图

官方图&#xff1a; 流程图&#xff1a; #mermaid-svg-2smjE8VYydjtLH0p {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-2smjE8VYydjtLH0p .error-icon{fill:#552222;}#mermaid-svg-2smjE8VYydjtLH0p .error-tex…

蓝桥杯2025年第十六届省赛真题-水质检测

C语言代码&#xff1a; #include <stdio.h> #include <string.h>#define MAX_LEN 1000000int main() {char a[MAX_LEN 1], b[MAX_LEN 1];// 使用 scanf 读取字符数组scanf("%s", a);scanf("%s", b);int ans 0;int pre -1;int state -1;i…

[Windows] 东芝存储诊断工具1.30.8920(20170601)

[Windows] 东芝存储诊断工具 链接&#xff1a;https://pan.xunlei.com/s/VOPpMjGdWZOLceIjxLNiIsIEA1?pwduute# 适用型号 东芝消费类存储产品&#xff1a; 外置硬盘&#xff1a;Canvio 系列 内置硬盘&#xff1a;HDW****&#xff08;E300 / N300 / P300 / S300 / V300 / X30…

Linux网络编程day7 线程池and UDP

线程池 typedef struct{void*(*function)(void*); //函数指针&#xff0c;回调函数void*arg; //上面函数的参数 }threadpool_task_t; //各子线程任务的结构体/*描述线程池相关信息*/struct threadpool_t{pthread_mutex_t lock; …

ABB电机保护单元通过Profibus DP主站转Modbus TCP网关实现上位机通讯

ABB电机保护单元通过Profibus DP主站转Modbus TCP网关实现上位机通讯 在工业自动化领域&#xff0c;设备之间的通信至关重要。Profibus DP是一种广泛应用的现场总线标准&#xff0c;而Modbus TCP则是一种基于以太网的常见通信协议。将Profibus DP主站转换为Modbus TCP网关&…

迪士尼机器人BD-X 概况

这些机器人代表着迪士尼故事叙述与非凡创新的完美结合。它们不仅栩栩如生&#xff0c;还配备了先进的技术。 -迪士尼幻想工程研发部高级副总裁凯尔劳克林 幕景 BDX 机器人是由华特迪士尼公司的研究和幻想工程部门利用NVIDIA人工智能技术 (AI)开发的现实世界机器人&#xff0c;…

UE5骨骼插槽蓝图

首先在人物骨骼处添加插槽并命名&#xff0c;然后再选择添加预览资产把你要的模型&#xff08;静态网格体&#xff09;放上去。 选择绑定的骨骼再去右边相对位置、旋转等调整物体。 再去人物蓝图里面写就ok了

绘制拖拽html

<!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8" /> <meta name"viewport" content"widthdevice-width, initial-scale1" /> <title>拖拽绘制矩形框 - 可移动可调整大小</ti…

ggplot2 | GO barplot with gene list

1. 效果图 2. 代码 数据是GO的输出结果&#xff0c;本文使用的是 metascape 输出的excel挑选的若干行。 # 1. 读取数据 datread.csv("E:\\research\\scPolyA-seq2\\GO-APA-Timepoint\\test.csv", sep"\t") head(dat)# 2. 选择所需要的列 dat.usedat[, c(…

系统思考:短期困境与长期收益

最近在项目中&#xff0c;一直有学员会提到一个议题&#xff0c;如何平衡当前困境和长期收益&#xff1f; 我的思考是在商业和人生的路上&#xff0c;我们常常听到“鱼和熊掌不可兼得”的说法&#xff0c;似乎短期利益和长期目标注定是对立的。但事实上&#xff0c;鱼与熊掌是…

Cjson格式解析与接入AI大模型

JSON格式的解析与构造 基本概念 JSON是JavaScript Object Notation的简称&#xff0c;中文含义为“JavaScript 对象表示法”&#xff0c;它是一种数据交换的文本格式&#xff0c;而不是一种编程语言。 JSON 是一种轻量级的数据交换格式&#xff0c;采用完全独立于编程语言的…

基于英特尔 RealSense D455 结构光相机实现裂缝尺寸以及深度测量

目录 一&#xff0c;相机参数规格 二&#xff0c;结合YOLO实例分割实现裂缝尺寸以及深度测量 2.1 应用场景 2.2 实现流程 2.3 效果展示 2.4 精度验证 2.5 实物裂缝尺寸以及深度测量效果展示 一&#xff0c;相机参数规格 英特尔 RealSense D455 是英特尔 RealSense D400 系…

Nacos源码—7.Nacos升级gRPC分析四

大纲 5.服务变动时如何通知订阅的客户端 6.微服务实例信息如何同步集群节点 6.微服务实例信息如何同步集群节点 (1)服务端处理服务注册时会发布一个ClientChangedEvent事件 (2)ClientChangedEvent事件的处理源码 (3)集群节点处理数据同步请求的源码 (1)服务端处理服务注册…

TIME - MoE 模型代码 3.2——Time-MoE-main/time_moe/datasets/time_moe_dataset.py

源码&#xff1a;GitHub - Time-MoE/Time-MoE: [ICLR 2025 Spotlight] Official implementation of "Time-MoE: Billion-Scale Time Series Foundation Models with Mixture of Experts" 这段代码定义了一个用于时间序列数据处理的 TimeMoEDataset 类&#xff0c;支…

【某OTA网站】phantom-token 1004

新版1004 phantom-token 请求头中包含phantom-token 定位到 window.signature 熟悉的vmp 和xhs一样 最新环境检测点 最新检测 canvas 下的 toDataURL方法较严 过程中 会用setAttribute给canvas 设置width height 从而使toDataURL返回不同的值 如果写死toDataURL的返回值…