背景: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; } } } }