万网有网站建设吗/广告联盟怎么加入

万网有网站建设吗,广告联盟怎么加入,重庆建设岗位培训网站,mathilda wordpresspdf预览本来打算粗暴点,一次性查看全部,但是一个pdf四五百页导致手机端查看超出内存直接崩掉,崩掉会导致页面疯狂刷新,所以不得不进行优化 解决思路大致如下: canvas转为blob格式以图片的形式加载在页面(B…

pdf预览本来打算粗暴点,一次性查看全部,但是一个pdf四五百页导致手机端查看超出内存直接崩掉,崩掉会导致页面疯狂刷新,所以不得不进行优化
解决思路大致如下:

  1. canvas转为blob格式以图片的形式加载在页面(Blob URL 是基于磁盘的临时文件,可以减少内存占用)
  2. 分段按需加载,根据页面滑动位置决定加载哪页数据
  3. 历史pdf加载数据缓存,避免一直调用获取pdf逻辑,但不可缓存全部历史数据,变量数据过多也会导致崩掉
  4. 及时移除画布和图片,确保内存被释放

具体实现看代码吧!对了,我这里用的是vue3框架,方案大致都差不多,可供参考

  1. 安装 pdfjs-dist包(版本为4.10.38)
    npm install pdfjs-dist
  2. 使用
<template><div class="pdf-box"><van-loading v-if="pdfLoading && !isHasFirstPage" size="24px">内容正在玩命加载中,请稍后...</van-loading><div :style="(pdfLoading && !isHasFirstPage)?'position:fixed;transform: translateX(-200%);':''"><div v-for="page in pdfPages" :id="'__pdf_canvas_page_' + page" :key="page" /></div><van-loading v-if="pdfItemLoading && isHasFirstPage" size="24px" style="padding-top:0">滑慢点~,小的加载不过来啦...</van-loading></div>
</template><script setup>
import { ref, onMounted, nextTick, onUnmounted } from 'vue'
import * as pdfjsLib from 'pdfjs-dist'
import Worker from 'pdfjs-dist/build/pdf.worker.min.mjs?worker'const pdfjsWorker = new Worker()
let pdf = null
const pdfPages = ref(0) // pdf总页数
const pdfLoading = ref(true) // pdf 总页数获取loading
let cachedPages = new Map() // pdf历史 图片信息缓存
const pdfItemLoading = ref(false) // pdf 单独页面加载
const MAX_CACHED_PAGES = 6 // 最大缓存页面数
const lastScrollY = ref(0) // 最后一次滚动位置
const scrollDirection = ref('') // 页面滚动方向 up:上 down:下
const isHasFirstPage = ref(false) // 第一页是否已加载出来// 在组件挂载后加载 PDF
onMounted(() => {const pdfUrl = 'https://example.com/sample.pdf' // 替换为你的 PDF 文件 URLloadPdf(pdfUrl)window.addEventListener('scroll', handleScroll) // 滚动变化时更新条件
})
// 清理事件监听器
onUnmounted(() => {window.removeEventListener('scroll', handleScroll)if (pdf) {pdf.destroy()}
})
// 加载pdf
async function loadPdf(url) {pdfjsLib.GlobalWorkerOptions.workerPort = pdfjsWorkertry {const loadingTask = pdfjsLib.getDocument(url)pdf = await loadingTask.promisepdfPages.value = Number(pdf.numPages)pdfLoading.value = falseawait nextTick(() => {handleScroll()})} catch (err) {pdfLoading.value = falseconsole.error(err)}
}
// 渲染指定页面pdf
const renderPage = (pageNumber) => {return new Promise(() => {(async () => {const page = await pdf.getPage(pageNumber)const viewport = page.getViewport({ scale: 1.5 })const canvas = document.createElement('canvas')const ctx = canvas.getContext('2d')canvas.height = viewport.heightcanvas.width = viewport.widthawait page.render({ canvasContext: ctx, viewport }).promise// 将画布内容缓存为图片const blobURL = await canvasToBlobURL(canvas)const image = new Image()image.src = blobURL// 将画布内容转换为 Blob URLimage.id = `page-image-${pageNumber}`image.style.width = '100%'// 将图片添加到容器中const container = document.getElementById(`__pdf_canvas_page_${pageNumber}`)container.innerHTML = ''container.appendChild(image)// 缓存 Blob URL 和 Image 标签cachePage(pageNumber, { blobURL, image: image.src })pdfItemLoading.value = false// resolve()})()})
}
// 缓存页面
const cachePage = (pageNumber, data) => {cachedPages.set(pageNumber, data)if (cachedPages.size > 0) { // 第一页是否已加载出来isHasFirstPage.value = true}if (cachedPages.size > MAX_CACHED_PAGES) {// 如果缓存数量超过限制cachedPages = new Map([...cachedPages.entries()].sort((a, b) => a[0] - b[0])) // 排序let oldestPage = ''if (scrollDirection.value === 'up') { // 往上滑动 移除最后的页面const keysArray = [...cachedPages.entries()]oldestPage = keysArray[keysArray.length - 1][0]} else { // 往上滑动 移除最早的页面oldestPage = cachedPages.keys().next().value}if (oldestPage && pageNumber !== oldestPage) {unloadPage(oldestPage)}}
}
// 将画布内容转换为 Blob URL
const canvasToBlobURL = (canvas) => {return new Promise((resolve) => {canvas.toBlob((blob) => {const url = URL.createObjectURL(blob)resolve(url)})})
}
// 清除非可视pdf信息
const unloadPage = (pageNumber) => {const container = document.getElementById(`__pdf_canvas_page_${pageNumber}`)const canvas = document.getElementById(`page-${pageNumber}`)const image = document.getElementById(`page-image-${pageNumber}`)const cachedData = cachedPages.get(pageNumber)if (cachedData) {const rect = container.getBoundingClientRect()container.innerHTML = ''const div = document.createElement('div')div.style.height = rect.height + 'px'container.appendChild(div)if (cachedData.blobURL) {URL.revokeObjectURL(cachedData.blobURL)} // 释放 Blob URL}if (canvas) {canvas.remove()} // 移除画布if (image) {image.remove()} // 移除图片// 从缓存中移除页面cachedPages.delete(pageNumber)
}
// 处理滚动事件
function handleScroll() {// pdfconst windowHeight = window.innerHeightconst currentScrollY = window.scrollY// 判断往上滑动还是往下scrollDirection.value = currentScrollY > lastScrollY.value ? 'down' : 'up'lastScrollY.value = currentScrollYconst pdfPagesArr = Array.from({ length: pdfPages.value }, (_, i) => i + 1)pdfPagesArr.reduce((accumulatorPromise, next) => {return accumulatorPromise.then(() => {	// 上一个接口执行完毕再执行下一个const pageElement = document.getElementById('__pdf_canvas_page_' + next)if (pageElement) {const rect = pageElement.getBoundingClientRect()if (!pdfItemLoading.value) {if ((scrollDirection.value === 'up' ? rect.top < windowHeight + 200 : rect.top < windowHeight) && rect.bottom > 0) {if (cachedPages.has(next)) { // 已加载则跳过return}pdfItemLoading.value = truereturn renderPage(next) // 如果页面未加载,则加载该页}}}})}, Promise.resolve())
}
</script>

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

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

相关文章

PyCharm中使用pip安装PyTorch(从0开始仅需两步)

无需 anaconda&#xff0c;只使用 pip 也可以在 PyCharm 集成环境中配置深度学习 PyTorch。 本文全部信息及示范来自 PyTorch 官网。 以防你是super小白&#xff1a; PyCharm 中的命令是在 Python Console 中运行&#xff0c;界面左下角竖排图标第一个。 1. 安装前置包 numpy …

掌握新编程语言的秘诀:利用 AI 快速上手 Python、Go、Java 和 Rust

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…

【Vitis AIE】FPGA快速部署ConvNet 示例MNIST数据集

AIE-ML 上的 MNIST ConvNet 版本&#xff1a;Vitis 2024.2 简介 本教程在 AMD VersalTM 自适应 SoC AIE-ML 上实现了一个卷积神经网络分类器&#xff0c;用于识别来自 MNIST 数据库 的手写数字。目标是说明如何将一个简单的机器学习示例分区和向量化到 Versal AI 引擎。MNIS…

ubuntu桌面图标异常——主目录下的所有文件(如文档、下载等)全部显示在桌面

ubuntu桌面图标异常 问题现象问题根源系统级解决方案方法一:全局修改(推荐多用户环境)方法二:单用户修改(推荐个人环境)操作验证与调试避坑指南扩展知识参考文档问题现象 主目录文件异常显示 用户主目录(如/home/user/)下的所有文件(如文档、下载等)全部显示在桌面,…

OceanBase 4.3.3 AP 解析:应用 RoaringBitmaps 类型处理海量数据的判重和基数统计

对于大数据开发人员而言&#xff0c;处理海量数据的判重操作和基数统计是常见需求&#xff0c;而 RoaringBitmap类型及其相关函数是当前非常高效的一种解决方案&#xff0c;许多大数据库产品已支持RoaringBitmap类型。OceanBase 4.3.3版本&#xff0c;作为专为OLAP场景设计的正…

W25Qxx

概述 FLASH FLASH是一种是非易失性存储器&#xff0c;即掉电后不会丢失数据&#xff0c;这和RAM&#xff08;随机存储器&#xff09;不同。 FLASH比起同作用的EEPROM有价格低的优点 FLASH的擦除操作是以扇区为单位的&#xff08;比起EEPROM来说操作较为不方便&#xff09; 芯片…

网络不可达

导致此问题原因较多&#xff0c;我只针对一种情况进行讨论&#xff0c;如果和文中症状不同&#xff0c;另寻他处&#xff0c;或者死马当活马医&#xff08;&#xff1f;&#xff09; 如需转载&#xff0c;标记出处 症状&#xff1a; 1.ping命令网络不可达 2.ifconfig中网卡en…

【AI News | 20250322】每日AI进展

AI Repos 1、DeTikZify 可以把草图或图形转换成TikZ代码的模型&#xff0c;可用来绘制复杂的科学图表&#xff0c;输入草图或文字描述即可转换成TikZ代码。DeTikZify强大的地方在于它能理解图表的语义信息&#xff0c; 能识别图表中的不同组成部分及其含义&#xff0c;比如坐标…

Debian12生产环境配置笔记

在 Debian 12 上进行生产环境配置的详细步骤&#xff0c;涵盖软件更新、基础软件安装、Docker 及 Redis 部署&#xff0c;以及 Nginx 配置多个虚拟主机等内容。所有命令均以 root 用户身份执行&#xff0c;无需添加 sudo 1. 更新软件 首先&#xff0c;确保系统上的所有软件包…

UE AI 模型自动生成导入场景中

打开小马的weix 关注下 搜索“技术链” 回复《《动画》》 快速推送&#xff1b; 拿到就能用轻松解决&#xff01;帮忙点个关注吧&#xff01;

【最后203篇系列】022 用Deepseek14b提取新闻事件

这算是之前一直想做的一件事&#xff0c;趁周末赶快做了。 业务意义&#xff1a;现实中有大量的舆情&#xff0c;这对我们的决策会有比较重要的作用 技术依赖&#xff1a; 1 模型基础能力2 消息队列3 异步获取消息4 时间序列库 1 模型基础能力 大模型发展到现在&#xff0…

Cursor的五种高级用法

文章目录 代码编写写作编辑自动生成工作流搞定开源项目数据处理参考 代码编写 Cursor 最基本的功能是帮助你编写代码。只需使用 Composer&#xff08;CtrlI&#xff09;&#xff0c;描述你想要实现的功能&#xff0c;Cursor 就能生成相应的代码。不满意&#xff1f;直接告诉它…

LeetCode hot 100 每日一题(13)——73. 矩阵置零

这是一道难度为中等的题目&#xff0c;让我们来看看题目描述&#xff1a; 给定一个 _m_ x _n_ 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 提示&#xff1a; m matrix.lengthn matrix[0].length1 < m, n …

Java基础编程练习第34题-正则表达式

在Java里&#xff0c;正则表达式是一种强大的文本处理工具&#xff0c;它可以用于字符串的搜索、替换、分割和校验等操作。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。Java通过java.util.regex包提供了对正则表达式的支持。 以下是正则表达式在Jav…

基于基于eFish-SBC-RK3576工控板的智慧城市边缘网关

此方案充分挖掘eFish-SBC-RK3576的硬件潜力&#xff0c;可快速复制到智慧园区、交通枢纽等场景。 方案亮点 ‌接口高密度‌&#xff1a;单板集成5GWiFi多路工业接口&#xff0c;减少扩展复杂度。‌AIoT融合‌&#xff1a;边缘端完成传感器数据聚合与AI推理&#xff0c;降低云端…

redis解决缓存穿透/击穿/雪崩

文章目录 1.缓存穿透1.1 概念1.2 解决方案1.2.1 缓存空对象1.2.2 布隆过滤 1.2 店铺查询使用缓存穿透解决方案1.2.1 流程 2.缓存雪崩2.1 什么是缓存雪崩&#xff1f;2.2 雪崩解决方案 3.缓存击穿3.1 什么是缓存击穿&#xff1f;3.2解决方案3.2.1 基于互斥锁解决缓存击穿问题&am…

第十六届蓝桥杯康复训练--6

题目链接&#xff1a;790. 数的三次方根 - AcWing题库 思路&#xff1a;二分&#xff0c;注意正负号和小数判断退出的方法&#xff08;虽然正负无所谓&#xff09; 代码&#xff1a; #include<bits/stdc.h> using namespace std;#define exs 0.00000018812716007232667…

【AVRCP】深度剖析 AVRCP 中 Generic Access Profile 的要求与应用

目录 一、GAP基础架构与核心要求 1.1 GAP在蓝牙体系中的定位 1.2 核心模式定义 二、AVRCP对GAP的增强要求 2.1 模式扩展规范 2.2 空闲模式过程支持 三、安全机制实现细节 3.1 认证与加密流程 3.2 安全模式要求 四、设备发现与连接建立 4.1 发现过程状态机 4.2 连接…

DeepSeek和Kimi在Neo4j中的表现

以下是2个最近爆火的人工智能工具&#xff0c; DeepSeek:DeepSeek Kimi: Kimi - 会推理解析&#xff0c;能深度思考的AI助手 1、提示词&#xff1a; 你能帮我生成一个知识图谱吗&#xff0c;等一下我会给你一篇文章&#xff0c;帮我从内容中提取关键要素&#xff0c;然后以N…

相机光学中一些疑难问题的解释

工业机器视觉系统广泛应用于自动化生产、质量控制、物体检测等领域&#xff0c;而光学原理和镜头选择是确保其精准度和高效性的关键因素。 1. 为什么镜头的最大光圈处通常成像不佳&#xff1f; 在许多摄影场景中&#xff0c;最大光圈&#xff08;例如F1.2、F1.8&#xff09;是…