2024-03-18 16:20:14 +08:00

215 lines
7.6 KiB
JavaScript

import {workerStr} from './worker.js';
import {pdfLibJsStr} from './pdf.js';
import {download as downloadFile, getUrl, loadScript} from '../../../utils/url';
import omit from 'lodash/omit';
const pdfJsLibSrc = `data:text/javascript;base64,${pdfLibJsStr}`;
const PdfJsWorkerSrc = `data:text/javascript;base64,${workerStr}`;
let pdfJsLibLoaded = false;
let workerLoaded = false;
class JsPdfPreview{
container = null;
wrapper = null;
wrapperMain = null;
options = {};
requestOptions = {};
pdfDocument = null;
loopCheckTimer = null;
constructor(container, options={}, requestOptions={}) {
this.container = container;
this.options = {
staticFileUrl: 'https://unpkg.com/pdfjs-dist@3.1.81/',
...options
};
this.requestOptions = requestOptions;
this.createWrapper();
}
createWrapper(){
this.wrapper = document.createElement('div');
this.wrapper.className = 'vue-office-pdf';
this.wrapper.setAttribute('style', 'text-align: center;overflow-y: auto;');
this.container.appendChild(this.wrapper);
}
createWrapperMain(){
this.wrapperMain = document.createElement('div');
this.wrapperMain.className = 'vue-office-pdf-wrapper';
this.wrapperMain.setAttribute('style', 'background: gray; padding: 30px 0;position: relative;');
this.wrapper.appendChild(this.wrapperMain);
}
createCanvas(num){
let existCanvas = this.wrapperMain.querySelectorAll('canvas');
if(existCanvas[num -1]){
return [existCanvas[num -1], existCanvas[num -1].getContext('2d')];
}
const canvas = document.createElement('canvas');
canvas.setAttribute('style', 'width:100%');
this.wrapperMain.appendChild(canvas);
return [canvas, canvas.getContext('2d')];
}
installPdfScript() {
return loadScript(pdfJsLibSrc).then(() => {
if (window.pdfjsLib && !workerLoaded) {
workerLoaded = true;
window.pdfjsLib.GlobalWorkerOptions.workerSrc = PdfJsWorkerSrc;
} else {
return Promise.reject('window.pdfjsLib未找到');
}
});
}
waitPdfjsLoad(){
return new Promise((resolve)=>{
const loopCheck = () =>{
if(window.pdfjsLib) {
resolve();
}else{
this.loopCheckTimer = setTimeout(loopCheck, 10);
}
};
loopCheck();
});
}
checkPdfLib() {
if (window.pdfjsLib) {
return Promise.resolve();
}
if(!pdfJsLibLoaded){
pdfJsLibLoaded = true;
return this.installPdfScript();
}else{
return this.waitPdfjsLoad();
}
}
getDocument(src){
const loadingTask = window.pdfjsLib.getDocument({
url: getUrl(src),
httpHeaders: this.requestOptions && this.requestOptions.headers,
withCredentials: this.requestOptions && this.requestOptions.withCredentials,
cMapUrl: `${this.options.staticFileUrl.endsWith('/') ? this.options.staticFileUrl : this.options.staticFileUrl + '/'}cmaps/`,
cMapPacked: true,
enableXfa: true,
...omit(this.options, ['width', 'staticFileUrl'])
});
return loadingTask.promise;
}
renderSinglePage(num){
return this.pdfDocument.getPage(num).then((pdfPage) => {
const viewport = pdfPage.getViewport({scale: 2});
const outputScale = window.devicePixelRatio > 2 ? 1.5 : 2;
let [canvas, ctx] = this.createCanvas(num);
canvas.width = Math.floor(viewport.width * outputScale);
canvas.height = Math.floor(viewport.height * outputScale);
let domWidth = Math.floor(viewport.width);
let domHeight = Math.floor(viewport.height);
if (this.options.width) {
let scale = this.options.width / domWidth;
domWidth = Math.floor(this.options.width);
domHeight = Math.floor(domHeight * scale);
}
let wrapperWidth = this.wrapperMain.getBoundingClientRect().width - 20;
if(domWidth > wrapperWidth){
let scale = wrapperWidth / domWidth;
domWidth = Math.floor(wrapperWidth);
domHeight = Math.floor(domHeight * scale);
}
canvas.style.width = domWidth + 'px';
canvas.style.height = domHeight + 'px';
const transform = outputScale !== 1
? [outputScale, 0, 0, outputScale, 0, 0]
: null;
const renderTask = pdfPage.render({
canvasContext: ctx,
transform,
viewport
});
return renderTask.promise.then(() => {
if (this.pdfDocument.numPages > num) {
return this.renderSinglePage(num + 1);
}
});
});
}
renderPage(){
if(!this.wrapperMain){
this.createWrapperMain();
}else{
let canvas = this.wrapperMain.querySelectorAll('canvas');
if(canvas.length > this.pdfDocument.numPages){
for(let i = canvas.length-1; i >= this.pdfDocument.numPages; i--){
this.wrapperMain.removeChild(canvas[i]);
}
}
}
return this.renderSinglePage(1);
}
clearAllCanvas(){
if(this.wrapperMain){
this.wrapper.removeChild(this.wrapperMain);
this.wrapperMain = null;
}
}
setOptions(options) {
this.options = options;
}
setRequestOptions(requestOptions) {
this.requestOptions = requestOptions;
}
preview(src){
return new Promise(((resolve, reject) => {
if(!src){
this.clearAllCanvas();
reject(new Error('预览地址不能为空'));
return;
}
this.checkPdfLib().then(_=>{
this.getDocument(src).then(pdf=>{
this.pdfDocument && this.pdfDocument.destroy();
this.pdfDocument = pdf;
this.renderPage().then(_=>{
resolve();
}).catch(e=>{
this.clearAllCanvas();
reject(e);
});
}).catch(e=>{
this.clearAllCanvas();
reject(e);
});
}).catch(e=>{
this.clearAllCanvas();
reject(e);
});
}));
}
rerender(){
return this.renderPage().then(_=>{
return Promise.resolve();
}).catch(e=>{
this.clearAllCanvas();
return Promise.reject(e);
});
}
save(fileName){
this.pdfDocument && this.pdfDocument._transport && this.pdfDocument._transport.getData().then(fileData=>{
downloadFile(fileName || `js-preview-pdf-${new Date().getTime()}.pdf`,fileData.buffer);
});
}
destroy(){
this.container.removeChild(this.wrapper);
this.container = null;
this.wrapper = null;
this.wrapperMain = null;
this.options = {};
this.requestOptions = {};
this.pdfDocument && this.pdfDocument.destroy();
this.pdfDocument = null;
this.loopCheckTimer && clearTimeout(this.loopCheckTimer);
}
}
export function init(container, options, requestOptions){
return new JsPdfPreview(container, options, requestOptions);
}