东莞市做网站的/百度导航下载2022最新版官网
实现样式
需求
实现PDF上传预览,并且不能下载
第一次实现:用vue-pdf,将上传的文件用base64传给前端展示
问题:
- 水印第一次加载有后面又没有了。
- 当上传大的pdf文件后,前端获取和渲染又长又慢,甚至不能用
修改实现模式
- 前端上传PDF,后端将PDF转化成一页一页的图片
- 前端根据page去获取一页一页的PDF图片,类似于百度文库
实现思路
配合后端实现思路
- 获取全部页数,先把侧边栏的元素画出来占个位置
- 获取已经看到的页数,没有默认1
- 渲染上次看到的页数,同时侧边栏滚动到相同的index位置,通过监听元素是否进入视口去获取base64图片
- 已经获取回来的图片不再去请求
主要重点难点是侧边栏懒加载、定位、等比例展示图片
<div class="pdf-viewer"><div class="pdf-main"><canvas id="pdf-view"></canvas></div><div class="pdf-list" :class="{ collapse: collapse }"><divclass="pdf-item":class="{ active: currentPage === index }"v-for="index in pageTotalNum":key="index"@click="changePage(index)":data-index="index"><img :src="imgList[index - 1]" alt="" /></div></div></div><script>
let observer = null;
export default {name: "PDFView",data() {return {currentPage: 1, //当前页数pageTotalNum: 1, //总页数imgList: [], //base64图片列表updateTimer: null};},watch: {/*** @description 监听当前页变化 滚动列表到顶部*/currentPage() {this.$nextTick(() => {const activeEl = document.querySelector(".pdf-list .active");if (activeEl) {document.querySelector(".pdf-list").scrollTo({top: activeEl.offsetTop - 20,behavior: "smooth",});// 解决进来会请求当前页数 前面所有图片setTimeout(() => {if (observer) {observer.disconnect();}this.isEnter();}, 500);}// 切换页面 将查看区域滚动到最上面const mainEl = document.querySelector(".pdf-main");mainEl.scrollTo({top: 0,});});},},mounted() {this.getPageTotal();},beforeDestroy() {if (observer) {observer.disconnect();}},methods: {/*** @description 获取pdf总页数*/getPageTotal() {const params = {id: this.$route.query.id,};apiGetViewPdfPageTotal(params).then((response) => {this.pageTotalNum = response.data;this.updateStudy(true);});},/*** @description 切换当前页*/changePage(index) {this.currentPage = index;this.updateStudy();if (this.imgList[index - 1]) {this.drawImage(this.imgList[index - 1]);} else {this.getPdf();}},/*** @description 上一页*/prePage() {let page = this.currentPage;if (page !== 1) {page = page > 1 ? page - 1 : this.pageTotalNum;this.currentPage = page;this.updateStudy();if (this.imgList[page - 1]) {this.drawImage(this.imgList[page - 1]);} else {this.getPdf();}}},/*** @description 下一页*/nextPage() {let page = this.currentPage;if (page !== this.pageTotalNum) {page = page < this.pageTotalNum ? page + 1 : 1;this.currentPage = page;this.updateStudy();if (this.imgList[page - 1]) {this.drawImage(this.imgList[page - 1]);} else {this.getPdf();}}},/*** @description 更新学习 flag=true第一次进入*/updateStudy(flag = false) {const params = {courseId: this.$route.query.id,pageRate: this.currentPage,flag,totalPageRate: this.pageTotalNum,};apiUpdateStudy(params).then((response) => {this.currentPage = response.data.pageRate;if (flag) {this.updateTimer = setInterval(() => {this.updateStudy();}, 1000 * 10);}if (flag) {this.getPdf();// 解决第一页进来不请求的问题,一页大概能展示4-5张if (this.currentPage < 5) {this.isEnter();}}})},/*** @description 查看资料*/getPdf() {const params = {id: this.$route.query.id,page: this.currentPage,};apiGetPdf(params).then((response) => {let base64 = "data:image/png;base64," + response.data;this.drawImage(base64);});},/*** @description 将base64图片 画到canvas上*/drawImage(base64) {const canvas = document.getElementById("pdf-view");const context = canvas.getContext("2d");const image = new Image();image.src = base64;image.onload = () => {const proportion = image.width / image.height;// 获取style设置width:100% 的canvas宽度const canvasWidth = canvas.offsetWidth;// 图片宽度与canvas宽度比例const canvasWidthProportion = image.width / canvasWidth;// canvas宽度设置为宽度canvas.width = image.width;// 根据图片比例和宽度比例计算出canvas高度canvas.height = (canvasWidth / proportion) * canvasWidthProportion;context.drawImage(image, 0, 0);};},/*** @description 监听元素进入视口*/isEnter() {observer = new IntersectionObserver((entries) => {entries.forEach((entry) => {const target = entry.target;const index = target.dataset.index;if (entry.isIntersecting) {if (!this.imgList[index - 1]) {this.getImgList(index);}} else {// console.log("元素离开视口", index);}});});this.$nextTick(() => {//将所有侧边栏的元素进行监听const els = document.querySelectorAll(".pdf-item");Array.from(els).forEach((el) => {observer.observe(el);});});},/*** @description 滚动获取图片*/getImgList(index) {const params = {id: this.$route.query.id,page: index,};apiGetPdf(params).then((response) => {let base64 = "data:image/png;base64," + response.data;this.imgList[index - 1] = base64;// 解决请求回来页面没更新的问题this.$forceUpdate();});},},
};
</script><style lang="scss" scoped>
.pdf-container {width: 100%;height: 100%;color: #999;
}
.pdf-viewer {width: 100%;height: calc(100vh - 50px - 30px - 60px - 6px);position: relative;display: flex;
}
.pdf-list {width: 240px;overflow-y: auto;display: flex;flex-direction: column;padding: 20px;background: #000;box-sizing: border-box;// transition: all 0.3s ease-in-out;border-left: 1px solid #999;&::-webkit-scrollbar {width: 0px;}.pdf-item {height: 183px;min-height: 183px;display: inline-flex;justify-content: center;align-items: center;cursor: pointer;overflow: hidden;&:hover {::v-deep img {transition: all 0.5s ease-in-out;transform: scale(1.1);}}&.active {box-shadow: 0px 0px 0px 4px #e6a23c;}&:not(:last-child) {margin-bottom: 10px;}img {pointer-events: none;width: 100%;// height: 100%;}}&.collapse {width: 0;padding: 0;}
}
.pdf-main {flex: 1;// width: 100%;// height: 100%;overflow-y: auto;background: #000;position: relative;padding: 10px 0;&::-webkit-scrollbar {width: 0px;}
}
.handle-btn {background: #000;display: flex;font-size: 12px;position: relative;height: 60px;padding: 0 6px;border-bottom: 1px solid #999;.right {width: 240px;display: flex;align-items: center;justify-content: flex-end;font-size: 32px;}.main {flex: 1;display: flex;align-items: center;justify-content: center;font-size: 32px;margin-left: 250px;.pagination {display: flex;align-items: center;margin: 0 10px;.pagination-info {font-size: 14px;margin: 0 8px;}}.zoom {display: flex;align-items: center;margin: 0 10px;.scale {font-size: 14px;margin: 0 8px;}}}.tips {color: #e6a23c;font-size: 12px;}.start-test {display: flex;align-items: center;}.time {position: absolute;left: 6px;top: 50%;transform: translateY(-50%);> span {display: inline-block;margin-left: 10px;}}
}
i {cursor: pointer;&:hover {color: #fff;}
}
#pdf-view {width: 100%;// height: 100%;padding: 10px;
}
</style>
相关文章:

Vue实现图片预览,侧边栏懒加载,不用任何插件,简单好用
实现样式 需求 实现PDF上传预览,并且不能下载 第一次实现:用vue-pdf,将上传的文件用base64传给前端展示 问题: 水印第一次加载有后面又没有了。当上传大的pdf文件后,前端获取和渲染又长又慢,甚至不能用 修…...

Spring依赖注入之setter注入与构造器注入以及applicationContext.xml配置文件特殊值处理
依赖注入之setter注入 在管理bean对象的组件的时候同时给他赋值,就是setter注入,通过setter注入,可以将某些依赖项标记为可选的,因为它们不是在构造对象时立即需要的。这种方式可以减少构造函数的参数数量,使得类的构…...

碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测,预测新数据
碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测,预测新数据 目录 碳排放预测 | Matlab实现LSTM多输入单输出未来碳排放预测,预测新数据预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现LSTM长短期记忆神经网络多输入单输出未来…...

手拉手JavaFX UI控件与springboot3+FX桌面开发
目录 javaFx文本 javaFX颜色 字体 Label标签 Button按钮 //按钮单击事件 鼠标、键盘事件 //(鼠标)双击事件 //键盘事件 单选按钮RadioButton 快捷键、键盘事件 CheckBox复选框 ChoiceBox选择框 Text文本 TextField(输入框)、TextArea文本域 //过滤 (传入一个参数&a…...
02 分解质因子
一、数n的质因子分解 题目描述: 输入一个数n(n<10^6),将数n分解质因数,并按照质因数从小到大的顺序输出每个质因数的底数和指数。 输入 5 输出 5 1 输入 10 输出 2 1 5 1 朴素解法: 首先求出1~n的所有质数…...

科技赋能智慧水利——山海鲸软件水利方案解析
作为山海鲸可视化软件的开发者,我们深感荣幸能为我国智慧水利建设提供强大助力。作为钻研数字孪生领域的开创者,我们希望不仅能为大家带来免费好用,人人都能用起来的数字孪生产品,还希望以其独特的技术优势和创新设计理念…...

C4.5决策树的基本建模流程
C4.5决策树的基本建模流程 作为ID3算法的升级版,C4.5在三个方面对ID3进行了优化: (1)它引入了信息值(information value)的概念来修正信息熵的计算结果,以抑制ID3更偏向于选择具有更多分类水平…...

本科毕业设计过程中应该锻炼的能力 (深度学习方向)
摘要: 本文以本科毕业设计做深度学习方向, 特别是全波形反演为例, 描述学生应在此过程中锻炼的能力. 搭建环境的能力. 包括 Python, PyTorch 等环境的安装.采集数据的能力. 包括 OpenFWI 等数据集.查阅资料的能力. 包括自己主要参考的文献, 以及其它相关文献 (不少于 20 篇). …...

深度学习——pycharm远程连接
目录 远程环境配置本地环境配置(注意看假设!!!这是很多博客里没写的)步骤1步骤2步骤2.1 配置Connection步骤2.2 配置Mappings 步骤3 配置本地项目的远程解释器技巧1 pycharm中远程终端连接技巧2 远程目录技巧3 上传代码文件技巧4 …...

信号量机制解决经典同步互斥问题
生产者 / 消费者问题、读者 / 写者问题和哲学家问题是操作系统的三大经典同步互斥问题。本文将介绍这三个问题的基本特点以及如何用信号量机制进行解决。 在分析这三个问题之前,我们首先需要了解用信号量机制解决同步互斥问题的一般规律: 实现同步与互斥…...

java基础09-==和equals()的区别,附代码举例
和equals()的区别 在Java中,和equals()是两个不同的运算符,它们在比较对象时有着本质的区别。 运算符: 用于比较两个基本数据类型(如int、char等)或两个对象的引用。 当用于比较基本数据类型时,它会比较它们的值。 当…...

qml与C++的交互
qml端使用C对象类型、qml端调用C函数/c端调用qml端函数、qml端发信号-连接C端槽函数、C端发信号-连接qml端函数等。 代码资源下载: https://download.csdn.net/download/TianYanRen111/88779433 若无法下载,直接拷贝以下代码测试即可。 main.cpp #incl…...

LabVIEW电路板插件焊点自动检测系统
LabVIEW电路板插件焊点自动检测系统 介绍了电路板插件焊点的自动检测装置设计。项目的核心是使用LabVIEW软件,开发出一个能够自动检测电路板上桥接、虚焊、漏焊和多锡等焊点缺陷的系统。 系统包括成像单元、机械传动单元和软件处理单元。首先,利用工业相…...

第十一站:多态练习ODU
实现动态切换 ODU.h #pragma once #include <iostream> using namespace std; #define ODU_TYPE_311_FLAG "311" #define ODU_TYPE_335_FLAG "335" enum class ODU_TYPE {ODU_TYPE_311,ODU_TYPE_335,ODU_TYPE_UNKNOW };class ODU{ public:ODU();//发…...

【深度学习】详解利用Matlab和Python中 LSTM 网络实现序列分类
🔗 运行环境:Matlab、Python 🚩 撰写作者:左手の明天 🥇 精选专栏:《python》 🔥 推荐专栏:《算法研究》 🔐#### 防伪水印——左手の明天 ####🔐 💗 大家好🤗🤗🤗,我是左手の明天!好久不见💗 💗今天分享Matlab深度学习—— LSTM 网络实现序列分...

Unity 工厂方法模式(实例详解)
文章目录 在Unity中,工厂方法模式是一种创建对象的常用设计模式,它提供了一个接口用于创建对象,而具体的产品类是由子类决定的。这样可以将对象的创建过程与使用过程解耦,使得代码更加灵活和可扩展。 工厂模式的主要优点如下&…...

2024年美赛数学建模思路 - 案例:异常检测
文章目录 赛题思路一、简介 -- 关于异常检测异常检测监督学习 二、异常检测算法2. 箱线图分析3. 基于距离/密度4. 基于划分思想 建模资料 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 一、简介 – 关于异常…...

一键完成,批量转换HTML为PDF格式的方法,提升办公效率
在当今数字化的时代,HTML和PDF已经成为两种最常用的文件格式。HTML用于网页内容的展示,而PDF则以其高度的可读性和不依赖于平台的特性,成为文档分享和传播的首选格式。然而,在办公环境中,我们经常需要在这两种格式之间…...

【重点问题】攻击面发现及管理
Q1:在使用长亭云图极速版时,是否需要增设白名单扫描节点? 长亭云图极速版高级网络安全产品基于一种理念,即攻击面发现是一个不断变换且需要持续对抗的过程。在理想的情况下,用户应当在所有预置防护设施发挥作用的环境…...

UE4外包团队:国外使用UE4虚幻引擎制作的十个知名游戏
1.俄罗斯方块效果(任天堂 Switch、PlayStation 4、PC、Xbox) 2.耀西的手工世界(任天堂 Switch) 3. Final Fantasy 7 Remake Intergrade (PlayStation, PC) 4.《堡垒之夜》(PC、Nintendo Switch、PlayStation、Xb…...

解决springboot+mybatisplus返回时间格式带T
原因:我service实现类的代码是 Overridepublic Map<String, Object> queryDictPage(Map<String, Object> queryMap) {Map<String,Object> map new HashMap<>();QueryWrapper<Dict> wrapper new QueryWrapper<>(); // …...

纯命令行在Ubuntu中安装qemu的ubuntu虚拟机,成功备忘
信息总体还算完整,有个别软件更新了名字,所以在这备忘一下 1. 验证kvm是否支持 ________________________________________________________________ $ grep vmx /proc/cpuinfo __________________________________________________________________…...

Vue的学习Day1_是什么以及两种风格
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Vue是什么?二、渐进式框架1.渐进式 三、Vue API风格1.选项式 API (Options API)2.组合式 API (Composition API) 四、Vue 开发前的准备 前言 放…...

磁悬浮人工心脏的不良事件分析:美国FDA数据库的启示
引言: 左心室辅助装置(LVAD)是治疗末期难治性心力衰竭(HF)患者的有效手段。磁悬浮人工心脏HeartMate-3(磁悬浮人工心脏)作为第三代LVAD,自2017年获得美国食品药品监督管理局&#x…...

HarmonyOS(十二)——全面认识HarmonyOS三种渲染控制
渲染控制概述 ArkUI通过自定义组件的build()函数和builder装饰器中的声明式UI描述语句构建相应的UI。在声明式描述语句中开发者除了使用系统组件外,还可以使用渲染控制语句来辅助UI的构建,这些渲染控制语句包括控制组件是否显示的条件渲染语句ÿ…...

SQL 系列教程(二)
目录 SQL DELETE 语句 DELETE 语句 演示数据库 DELETE 实例 删除所有行 SQL TOP, LIMIT, ROWNUM 子句 TOP 子句 演示数据库 SQL TOP、LIMIT 和 ROWNUM 示例 SQL TOP PERCENT 实例 添加WHERE子句 SQL MIN() 和 MAX() 函数 MIN() 和 MAX() 函数 演示数据库 MIN() …...

CSS实现文本和图片无限滚动动画
Demo图如下: <style>* {margin: 0;padding: 0;box-sizing: border-box;font-family: Poppins, sans-serif;}body {min-height: 100vh;background-color: rgb(11, 11, 11);color: #fff;display: flex;flex-direction: column;justify-content: center;align-i…...

MacOS 无法ping 通 github.com 解决方案
ping github.com 会显示请求超时: PING github.com (192.30.253.112): 56 data bytes Request timeout for icmp_seq 0 Request timeout for icmp_seq 1 Request timeout for icmp_seq 2 Request timeout for icmp_seq 3 Request timeout for icmp_seq 4 Request …...

Mac 也能玩文明6!下载安装详细教程
最近朋友给我分享了一个 Mac 玩文明6的方法,丝毫不卡顿,非常流畅,分享给大家 文明6是最新的文明系列游戏,和以往的文明游戏一样,玩家将从石器时代创建文明,然后迈向信息时代,最终通过军事、经济…...

git tag的用法详解
目录 一、tag标识一个commit 二、查看tag 三、对分支打tag 四、删除tag 五、根据某个tag来clone 一、tag标识一个commit tag是用于去标记一个特定的commit。通常,在进行编译部署之前,我们需要对某一个即将release的版本进行tag,例如tag为…...