评论

web-view嵌套H5预览PDF 垂直滚动动态拼接

web-view嵌套H5预览PDF

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

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

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

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

H5:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>PDF</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    body {
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
      background-color: #f5f5f5;
      overflow: hidden;
    }


    #pdf-container {
      position: relative;
      width: 100vw;
      height: 95vh;
      overflow-y: auto;
      /* 显示垂直滚动条 */
      background-color: white;
    }
    .spacer {
      width: 100%;
      height: 20px;
      /* 空白行的高度 */
      background-color: #f5f5f5;
      /* 空白行的背景颜色 */
    }
    .pdf-page {
      width: 100%;
      display: block;
    }
    #page-info {
      position: fixed;
      top: 12px;
      right: 12px;
      background: rgba(0, 0, 0, 0.6);
      color: white;
      padding: 6px 12px;
      border-radius: 16px;
      font-size: 14px;
      z-index: 1000;
      user-select: none;
    }
  </style>
</head>


<body>
  <div id="pdf-container">
    <!-- <div id="page-info">第 0 页 / 共 0 页</div> -->
  </div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/1.1.469/pdf.min.js"></script>
  <script>
    let pdfDoc = null;
    let currentPage = 1;
    let totalPages = 0;
    let scale = 1.5;
    let pageNum = 1;
    let isLoading = false; // 标记是否正在加载页面,防止重复加载
    PDFJS.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/1.1.469/pdf.worker.js';
     const pdfContainer = document.getElementById('pdf-container');
    const pageInfo = document.getElementById('page-info');

    function getUrlParam(name) {
        var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); // 构造一个含有目标参数的正则表达式对象
        var param = decodeURIComponent(window.location.search);
        var r = param.substr(1).match(reg); // 匹配目标参数
        //window.console.log(r)
        if (r != null) return r[2];
        return null; // 返回参数值
    };
    //标题
    let name = getUrlParam('n');
    document.title = decodeURIComponent(name);
    // 加载 PDF
    async function loadPDF(url) {
      try {
        pdfDoc = await PDFJS.getDocument(url).promise;
        totalPages = pdfDoc.numPages;
        renderPage(currentPage);
      } catch (error) {
        console.error('加载 PDF 失败:', error);
      }
    }




      // 渲染指定页面
    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; // 加载完成,取消标记
    }


监听滑动事件

               /* 触摸滑动事件(移动端) */
    		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);
    		});


PC 端滚轮事件

/* 滚轮/触摸上下滑动翻页 */
    let busy = false;
    const scrollDelay = 3000;      // 防抖时间 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;
      pageNum = target;
      busy = true;
      nextPage(pageNum).finally(() => busy = false);
    }
    /* 滚轮事件 */
    window.addEventListener('wheel', e => {
      go(e.deltaY > 0 ? 1 : -1);
    }, { passive: true });

    async function nextPage(pageNum) {
      await renderPage(pageNum);
    }

    // 初始化加载 PDF
    loadPDF(getUrlParam('u'));
  </script>
</body>
</html>


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>



最后一次编辑于  08-08  
点赞 0
收藏
评论
登录 后发表内容