pdf在前端網頁的顯示

诉诉飞飞發表於2024-04-11

背景:react框架
實現外掛:pdfjs-dist: "^2.0.943" (還有其他外掛 react-pdf , react-pdf-js , pdf.js 都可以嘗試一下呢)

實現效果:

實現程式碼 如下:

index.jsx

import React, { useState, useEffect } from 'react'; import { Spin } from 'antd'; import { RightOutlined, LeftOutlined, PlusOutlined, MinusOutlined } from '@ant-design/icons'; import testPdf from 'public/pdf/面試總結.pdf'; import './index.less'; const pdfjsLib = require('pdfjs-dist/build/pdf.min.js'); pdfjsLib.GlobalWorkerOptions.workerSrc = (typeof window !== 'undefined' ? window : {} ).pdfjsWorker = require('pdfjs-dist/build/pdf.worker.min.js'); const PdfTest = (props) => { const [pdfRefList, setPdfRefList] = useState([]); const [page, setPage] = useState(1); //當前頁 const [pages, setPages] = useState(null); //總頁數 const [scale, setScale] = useState(1.5); const [loadingPage, setLoadingPage] = useState(false); useEffect(() => { setLoadingPage(true); getDocument(page, testPdf); }, [page]); useEffect(() => { pdfRefList && pdfRefList.map((pdf) => { pdf.detail && pdf.detail.getPage(page).then(function (page) { const viewport = page.getViewport(scale); const canvas = document.getElementById('pdfCanvas'); const canvasContext = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; const renderContext = { canvasContext: canvasContext, viewport: viewport.clone({ rotation: 0 }), background: '#ddd' }; page.render(renderContext); setLoadingPage(false); }); }); }, [pdfRefList, scale]); const getDocument = (pageNum, href) => { const loadingTask = pdfjsLib.getDocument({ url: href, // pdf檔案地址 或者 請求資源地址 cMapPacked: true // 此引數需要設為true }); loadingTask.promise.then((loadedPdf) => { const pdf = [{ id: pageNum, detail: loadedPdf }]; setPages(loadedPdf.numPages); setPage(pageNum); setPdfRefList(pdf); }); }; const renderPagination = (page, pages) => { if (!pages) { return null; } let previousButton = ( <li className="previous" onClick={() => setPage(page - 1)}> <LeftOutlined /> </li> ); if (page === 1) { previousButton = ( <li className="previous disabled"> <LeftOutlined /> </li> ); } let nextButton = ( <li className="next" onClick={() => setPage(page + 1)}> <RightOutlined /> </li> ); if (page === pages) { nextButton = ( <li className="next disabled"> <RightOutlined /> </li> ); } return ( <ul className="pager"> {previousButton} <li className="pageNum">{page + '/' + pages}</li> {nextButton} </ul> ); }; const zoomIn = (val) => { if (scale > 0.75 || scale < 2) { if (val == '+') { setScale(scale + 0.25); } else { setScale(scale - 0.25); } } }; return ( <div className="page-content"> {/* pdf顯示 */} <div className="viewer"> {pdfRefList && pdfRefList.map((pdf) => { return ( <div className="canvasWrapper" key={pdf.id}> <Spin spinning={loadingPage}> <canvas id="pdfCanvas"></canvas> </Spin> </div> ); })} </div> <div className="pdfOperation"> {/* 分頁 */} {renderPagination(page, pages)} {/* 縮放按鈕 */} <div className="pdfTool"> <span className="zoomBtn" onClick={() => zoomIn('-')}> <MinusOutlined /> </span> <span className="scale">{scale * 100 + '%'}</span> <span className="zoomBtn" onClick={() => zoomIn('+')}> <PlusOutlined /> </span> </div> </div> </div> ); }; export default PdfTest;
index.less
.page-content{
    background: #f2f2f2;
    width: 100%;
    height: 100vh;
    overflow-y: auto;
    .viewer{
        overflow-y: auto;
        .ant-spin-container{
            margin: 0 auto;
            display: flex;
            justify-content: center;
        }
    }
    .pdfOperation{
        width: 100%;
        background: #f2f2f2;
        height: 32px;
        position: fixed;
        bottom: 0;
        left: 0;
        box-shadow: 0 -2px 2px 0 rgba(0, 0, 0, 0.05);
        z-index: 21;
        .pdfTool{
            display: flex;
            align-items: center;
            justify-content: center;
            position: absolute;
            right: 30%;
            top: 50%;
            transform: translateY(-50%);
            width: 100px;
            border-radius: 4px;
            .zoomBtn{
              font-size: 14px;
              color: rgba(#000,0.6);
              cursor: pointer;
            }
            .scale{
              padding: 0 12px;
              font-size: 12px;
            }
          }
      
          .pager{
            display: block;
            display: flex;
            align-items: center;
            justify-content: center;
            height: 32px;
            border-radius: 4px;
            width: 140px;
            position: absolute;
            left: 50%;
            transform: translateX(-50%);
            .pageNum{
              width: 100px;
              text-align: center;
              border-radius: 4px;
            }
            .previous,.next{
              padding: 0 16px;
              color: rgba(#000,0.8);
              cursor: pointer;
            }
            .disabled{
              color: rgba(#000,0.2);
              cursor: default;
            }
           
          }
    }
}

  

相關文章