Vue实现图片预览,侧边栏懒加载,不用任何插件,简单好用

实现样式

在这里插入图片描述

需求

实现PDF上传预览,并且不能下载

第一次实现:用vue-pdf,将上传的文件用base64传给前端展示
问题:

  1. 水印第一次加载有后面又没有了。
  2. 当上传大的pdf文件后,前端获取和渲染又长又慢,甚至不能用

修改实现模式

  1. 前端上传PDF,后端将PDF转化成一页一页的图片
  2. 前端根据page去获取一页一页的PDF图片,类似于百度文库

实现思路

配合后端实现思路

  1. 获取全部页数,先把侧边栏的元素画出来占个位置
  2. 获取已经看到的页数,没有默认1
  3. 渲染上次看到的页数,同时侧边栏滚动到相同的index位置,通过监听元素是否进入视口去获取base64图片
  4. 已经获取回来的图片不再去请求

主要难点是侧边栏懒加载和定位

 <div class="pdf-viewer">
   <div class="pdf-main">
     <canvas id="pdf-view"></canvas>
   </div>
   <div class="pdf-list" :class="{ collapse: collapse }">
     <div
       class="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);
        }
      });
    },
  },
  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 = () => {
        canvas.width = image.width;
        canvas.height = image.height;
        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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

2. figure 常见属性

2. figure 常见属性 一 figsize二 dpi三 facecolor四 edgecolor五 frameon 数据可视化是数据分析中不可或缺的一环&#xff0c;而Matplotlib作为Python中最流行的绘图库之一&#xff0c;扮演着重要的角色。在Matplotlib中&#xff0c;matplotlib.figure.Figure对象是构建图形的…

MyBatis详解(2)-- mybatis配置文件

MyBatis详解&#xff08;2&#xff09; mybatis配置文件 mybatis配置文件 1.构建SqlSessionFactory的依据。 2.MyBatis最为核心的内容&#xff0c;对MyBatis的使用影响很大。 3.配置文件的层次顺序不能颠倒&#xff0c;一旦颠倒会出现异常。 < c o n f i g u r a t i o n…

openresty 安装, nginx与 openresty

openresty VS nginx Nginx 是一款高性能的 Web 服务器和反向代理服务器&#xff0c;具备基础的功能如HTTP服务、负载均衡、反向代理以及动静分离等。它是许多互联网应用的核心组件&#xff0c;因其模块化和可扩展的设计而受到欢迎。1 OpenResty 是基于 Nginx 的 Web 平台&…

C++入门篇章1(C++是如何解决C语言不能解决的问题的)

目录 1.C关键字(以C98为例)2.命名空间2.1 命名空间定义2.2命名空间使用 3.C输入&输出4.缺省参数4.1缺省参数概念4.2 缺省参数分类 5. 函数重载5.1函数重载概念5.2 C支持函数重载的原理--名字修饰(name Mangling) 1.C关键字(以C98为例) C总计63个关键字&#xff0c;C语言32…

【操作系统基础】【CPU访存原理】:寄存 缓存 内存 外存、内存空间分区、虚拟地址转换、虚拟地址的映射

存储器怎么存储数据、内存空间分区、虚拟地址转换 计算机的存储器&#xff1a;寄存 缓存 内存 外存&#xff08;按功能划分&#xff09; 计算机的处理器需要一个存储器来存储大量的指令和数据以便自己不断取指执行和访问数据。 内存&#xff08;内存就是运行内存&#xff0c…

利用git上传本地文件

1、建立仓库 2.然后刷新网站&#xff0c;获取下载链接&#xff0c;备用。 3、接下来在本地创建一个文件夹&#xff0c; 4、把github上面的仓库克隆到本地 git clone https://github.com/xxxxx&#xff08;https://github.com/xxxxx替换成你之前复制的地址&#xff09; 5、把…

简单快速取消AlertDialog的白色背景框,AlertDialog设置圆角背景

问题描述&#xff1a; 产品需求弹出的提示框是圆角&#xff0c;使用shape 设置圆角背景后&#xff0c;弹出的AlertDialog提示框四个角有白色的背景&#xff0c;据分析这个背景是 AlertDialog 父组件的背景色。 解决方法&#xff1a; 将Dialog的背景设置为透明色&#xff0c;代…

生产力工具|卸载并重装Anaconda3

一、Anaconda3卸载 &#xff08;一&#xff09;官方方案一&#xff08;Uninstall-Anaconda3-不能删除配置文件&#xff09; 官方推荐的方案是两种&#xff0c;一种是直接在Anaconda的安装路径下&#xff0c;双击&#xff1a; &#xff08;可以在搜索栏或者使用everything里面搜…

两数之和[中等]

一、题目 给你一个下标从1开始的整数数组numbers&#xff0c;该数组已按非递减顺序排列&#xff0c;请你从数组中找出满足相加之和等于目标数target的两个数。如果设这两个数分别是numbers[index1]和numbers[index2]&#xff0c;则1 < index1 < index2 < numbers.len…

Oracle报错:ORA-12541:TNS:无监听程序 (很大概率是listener.log满了,4G就无法写入了)

目录标题 一、前提二、查看listener.log三、如果是listener.log满了&#xff0c;内存达到4G,可以使用以下方法解决。&#xff08;一&#xff09;停用服务&#xff08;二&#xff09;将满了的listener.log日志删除或者改名&#xff0c;然后新建一个一样的listener.log文件&#…

助力工业生产质检,基于YOLOv7【tiny/l/x】不同系列参数模型开发构建生产制造场景下布匹瑕疵缺陷检测识别分析系统

纯粹的工业制造没有办法有长久的发展过程&#xff0c;转制造为全流程全场景的生产智造才是未来最具竞争力的生产场景&#xff0c;在前面的开发实践中我们已经涉足工业生产场景下进行了很多实地的项目开发&#xff0c;如&#xff1a;PCB电路板缺陷检测、焊接缺陷检测、螺母螺钉缺…

面试题-【消息队列】

消息队列 问题1 如何进行消息队列的技术选型优点解耦 &#xff08;pub/sub模型&#xff09;异步&#xff08;异步接口性能优化&#xff09;削峰 使用消息队列的缺点几种消息队列的特性 问题2 引入消息队列之后该如何保证其高可用性RabbitMQ的高可用kafka高可用 问题3 在消息队列…

07 队列

目录 1.队列 2.实现 3.OJ题 1. 队列 只允许在一段进行插入数据操作&#xff0c;在另一端进行数据删除操作的特殊线性表&#xff0c;队列具有先进先出FIFO&#xff08;First In Firtst Out&#xff09;&#xff0c;插入操作的叫队尾&#xff0c;删除操作的叫队头 2. 实现 队列…

前端echarts图形报表常见的样式配置

文章目录 &#x1f412;个人主页&#x1f3c5;Vue项目常用组件模板仓库&#x1f4d6;前言&#xff1a;&#x1f415;1.深色主题&#x1f415;2.改变柱状图颜色&#x1f415;突然发现去问ai&#xff0c;更容易理解&#xff0c;那就不总结了 &#x1f412;个人主页 &#x1f3c5;…

太阳光模拟器汽车耐老化太阳跟踪聚光户外加速老化试验

1 范围 1.1 本标准适用于以太阳为光源的菲涅耳反射系统来进行汽车外饰材料的加速老化试验。 1.2 本标准规定的设备和方法可用于确定曝露于日光、热和潮湿下的汽车材料的相对耐老化性&#xff0c; 前提是假设试验期间发生的对材料加速老化速率起决定性作用的物理、化学变化机理…

缓存高并发问题

Redis 做缓存虽减轻了 DBMS 的压力&#xff0c;减小了 RT&#xff0c;但在高并发情况下也是可能会出现各种问题的。 缓存穿透 当用户访问的数据既不在缓存也不在数据库中时&#xff0c;就会导致每个用户查询都会“穿透”缓存“直抵”数据库。这种情况就称为缓存穿透。当高度发…

什么是网络?

你是一台电脑&#xff0c;你的名字叫 A 很久很久之前&#xff0c;你不与任何其他电脑相连接&#xff0c;孤苦伶仃。 直到有一天&#xff0c;你希望与另一台电脑 B 建立通信&#xff0c;于是你们各开了一个网口&#xff0c;用一根网线连接了起来。 用一根网线连接起来怎么就能&…

Oracle BIEE 示例(一)数据透视表2

1 背景 版本:BIEE 12C 视图:数据透视表 实现内容(顺序与具体内容不一致): 2 空列显示(方法一) 2.1 问题 列为空时,标题栏不显示信息。 2.2 期望 即使数据为空,也要显示列名。 2.3 官方资料 2.3.1 操作步骤 2.3.1.1 要在分析级别关闭空值隐藏,请执行以下操作…

不停机迁移,TDengine 在 3D 打印技术中的“焕新”之路

小T导读&#xff1a;自 2021 年我们正式使用 TDengine 至今已接近三年&#xff0c;现在 TDengine 已经成熟应用于我们多个项目当中&#xff0c;凭借着强大的读写存储能力&#xff0c;为我司多项业务的核心数据保驾护航。近期我们团队刚好完成 TDengine 2.x 到 3.x 的数据迁移&a…

基于EfficientNet(B0-B7)全系列不同参数量级模型开发构建中草药图像识别分析系统,实验量化对比不同模型性能

EfficientNet系列的模型在我们前面开发识别类项目或者是检测类项目都是比较少去使用的&#xff0c;一方面是技术本身迭代发展的速度是比较快的&#xff0c;可能新的东西还没学习更新的东西就出来了&#xff0c;另一方面是EfficientNet本身实际业务使用度并不高&#xff0c;可能…