极简PDF预览,单页垂直滚动加载,目前上线后没有遇到白屏问题

本次用到 pdf.min.js pdf.worker.js 1.1.469 版本 使用高版本 web-view 一些方法不支持。

并且使用cover-view 标签 按钮可以悬浮在web-view 之上 必须真机调试才有效果

监听滚动事件,快速来回滚动 页码数会错乱 暂时没有好的方法就去掉了

主要部分方法:

 // 渲染指定页面
    async function renderPage(pageNum) {
      if (!pdfDoc || isLoading) return;
      isLoading = true; // 标记正在加载
      const page = await pdfDoc.getPage(pageNum);
      const viewport = page.getViewport(1);
      // 创建新的 canvas 元素
      const canvas = document.createElement('canvas');
      canvas.className = 'pdf-page page-' + pageNum;
      canvas.width = viewport.width;
      canvas.height = viewport.height;
      const ctx = canvas.getContext('2d');
      const renderContext = {
        canvasContext: ctx,
        viewport: viewport
      };
      await page.render(renderContext).promise;
      // 将新 canvas 插入到容器中
      pdfContainer.appendChild(canvas);
      // 如果不是最后一页,添加一个空白行
      if (pageNum < totalPages) {
        const spacer = document.createElement('div');
        spacer.className = 'spacer';
        pdfContainer.appendChild(spacer);
      }
      // 更新页码信息
      // pageInfo.textContent = `第 ${pageNum} 页 / 共 ${totalPages} 页`;
      // 如果是第一页,滚动到顶部
      if (pageNum === 1) {
        pdfContainer.scrollTop = 0;
      }
      isLoading = false; // 加载完成,取消标记
    }

PC端滚轮事件 与 移动端 触摸滑动事件

/* 滚轮/触摸上下滑动翻页 */
		let busy = false;
		const scrollDelay = 1000;      // 防抖时间 ms
		let lastCall = 0;
		function go(delta) {           // delta = 1 下一页;-1 上一页
			const now = new Date().getTime();
			const target = pageNum + delta;
			var info = document.getElementsByClassName('pdf-page page-' + target);
			if (info.length > 0) {
				return;
			}
			if (now - lastCall < scrollDelay || target < 1 || target > totalPages || busy) return;
			lastCall = now;
			busy = true;
			pageNum = target;
			nextPage(pageNum).finally(() => busy = false);
		}

		/* 滚轮事件 */
		window.addEventListener('wheel', e => {
			go(e.deltaY > 0 ? 1 : -1, new Date().getTime());
		}, { passive: true });


		/* 触摸滑动事件(移动端) */
		let startY = 0;
		window.addEventListener('touchstart', e => { startY = e.touches[0].clientY });
		window.addEventListener('touchend', e => {
			const dy = startY - e.changedTouches[0].clientY;
			if (Math.abs(dy) > 60) go(dy > 0 ? 1 : -1, new Date().getTime());
		

H5 部署在业务域名下
小程序 web-view 应用(必须真机调试 才有效果):

.material-operation {
  position: fixed;  
  bottom: 0;
  z-index: 2;
.info-btn {
	height: 120rpx;
	display: flex;
	align-items: center;
	image,cover-image {
		width: 36rpx;
		height: 36rpx;
		margin-right: 2rpx;
		}		
         }
}
<web-view :src="info.viewUrl"> 
  <cover-view class="material-operation">
      <cover-view  class="info-btn" @click="fnCollect" style="width: 130rpx;"/>
  </cover-view>  
</web-view>

更多推荐