Files

268 lines
6.9 KiB
JavaScript
Raw Permalink Normal View History

2025-02-26 14:53:02 +08:00
import * as pdfJS from './pdfjs-4.0.379.min.mjs';
import * as pdfWorker from './pdfjs-4.0.379.worker.min.mjs';
if (pdfJS != null && pdfWorker != null) {
pdfJS.GlobalWorkerOptions.workerSrc = pdfWorker;
}
function getCanvas(item) {
if (isDomSupported() && typeof item === 'string') {
item = document.getElementById(item);
} else if (item && item.length) {
// support for array based queries
item = item[0];
}
if (item && item.canvas !== undefined && item.canvas) {
// support for any object associated to a canvas (including a context2d)
item = item.canvas;
}
return item;
}
const getPdf = (key) => {
const canvas = getCanvas(key);
return Object.values(pdfInstances).filter((c) => c.canvas === canvas).pop();
};
const pdfInstances = {};
class Pdf {
static instances = pdfInstances;
static getPdf = getPdf;
constructor(item) {
const canvas = getCanvas(item);
//const existingPdf = getPdf(canvas);
this.id = canvas.id;
this.canvas = canvas;
this.ctx = canvas.getContext('2d');
this.pdfDoc = null;
this.pageNum = 1;
this.pagesCount = 0;
this.pageRendering = false;
this.pageNumPending = null;
this.scale = 1;
this.rotation = 0;
pdfInstances[this.id] = this;
}
}
export function firstPage(dotNetHelper, elementId) {
const pdf = getPdf(elementId);
if (pdf == null || pdf.pageNum === 1)
return;
if (pdf.pageNum > 1)
pdf.pageNum = 1;
queueRenderPage(pdf, pdf.pageNum);
setPdfViewerMetaData(dotNetHelper, pdf);
}
export function gotoPage(dotNetHelper, elementId, gotoPageNum) {
const pdf = getPdf(elementId);
if (pdf == null || gotoPageNum < 1 || gotoPageNum > pdf.pagesCount)
return;
pdf.pageNum = gotoPageNum;
queueRenderPage(pdf, pdf.pageNum);
setPdfViewerMetaData(dotNetHelper, pdf);
}
export function lastPage(dotNetHelper, elementId) {
const pdf = getPdf(elementId);
if (pdf == null || (pdf.pageNum === 1 && pdf.pageNum === pdf.pagesCount))
return;
if (pdf.pageNum < pdf.pagesCount)
pdf.pageNum = pdf.pagesCount;
queueRenderPage(pdf, pdf.pageNum);
setPdfViewerMetaData(dotNetHelper, pdf);
}
export function nextPage(dotNetHelper, elementId) {
const pdf = getPdf(elementId);
if (pdf == null || pdf.pageNum === pdf.pagesCount)
return;
if (pdf.pageNum < pdf.pagesCount)
pdf.pageNum += 1;
queueRenderPage(pdf, pdf.pageNum);
setPdfViewerMetaData(dotNetHelper, pdf);
}
export function previousPage(dotNetHelper, elementId) {
const pdf = getPdf(elementId);
if (pdf == null || pdf.pageNum === 0 || pdf.pageNum === 1)
return;
if (pdf.pageNum > 0)
pdf.pageNum -= 1;
queueRenderPage(pdf, pdf.pageNum);
setPdfViewerMetaData(dotNetHelper, pdf);
}
export async function print(dotNetHelper, elementId, url) {
const pdfDoc = await pdfJS.getDocument(url).promise;
const pageRange = [1, 2, 3, 4]; // TODO: update this
const iframeEl = document.createElement('iframe');
iframeEl.style = 'display:none';
document.body.appendChild(iframeEl);
for (const pageNumber of pageRange) {
const page = await pdfDoc.getPage(pageNumber);
const viewport = page.getViewport({ scale: 1.5 });
const canvas = document.createElement("canvas");
canvas.height = viewport.height;
canvas.width = viewport.width;
//canvas.style.height = `${viewport.height * 2}px`;
//canvas.style.width = `${viewport.width * 2}px`;
const ctx = canvas.getContext('2d');
const renderContext = {
//intent: 'print',
canvasContext: ctx,
viewport: viewport
};
await page.render(renderContext).promise;
const iframeDoc = iframeEl.contentWindow.document;
iframeDoc.body.appendChild(canvas);
}
setTimeout(() => {
iframeEl.contentWindow.print();
iframeEl.remove();
},
1000);
}
export function rotate(dotNetHelper, elementId, rotation) {
const pdf = getPdf(elementId);
if (pdf == null || Number.isNaN(rotation) || rotation % 90 !== 0)
return;
pdf.rotation = rotation;
queueRenderPage(pdf, pdf.pageNum);
}
export function zoomInOut(dotNetHelper, elementId, scale) {
const pdf = getPdf(elementId);
if (pdf == null)
return;
if (!Number.isNaN(scale))
pdf.scale = scale;
queueRenderPage(pdf, pdf.pageNum);
}
// resize
// print
// download
// zoomreset
/*
firstPageButton.disabled = this.pageNumber <= 1;
lastPageButton.disabled = this.pageNumber >= this.pagesCount;
pageRotateCwButton.disabled = this.pagesCount === 0;
pageRotateCcwButton.disabled = this.pagesCount === 0;
*/
export function initialize(dotNetHelper, elementId, scale, rotation, url) {
const pdf = new Pdf(elementId);
pdf.scale = scale;
pdf.rotation = rotation;
pdfJS.getDocument(url).promise.then(function (doc) {
pdf.pdfDoc = doc;
pdf.pagesCount = doc.numPages;
renderPage(pdf, pdf.pageNum);
dotNetHelper.invokeMethodAsync('DocumentLoaded', { pagesCount: pdf.pagesCount, pageNumber: pdf.pageNum });
});
}
function isDomSupported() {
return typeof window !== 'undefined' && typeof document !== 'undefined';
}
/**
* If another page rendering in progress, waits until the rendering is
* finished. Otherwise, executes rendering immediately.
*/
function queueRenderPage(pdf, num) {
if (pdf.pageRendering) {
pdf.pageNumPending = num;
} else {
renderPage(pdf, num);
}
}
/**
* Get page info from document, resize canvas accordingly, and render page.
* @param num Page number.
*/
function renderPage(pdf, num) {
pdf.pageRendering = true;
// Using promise to fetch the page
pdf.pdfDoc.getPage(num).then((page) => {
const viewport = page.getViewport({ scale: pdf.scale, rotation: pdf.rotation });
pdf.canvas.height = viewport.height;
pdf.canvas.width = viewport.width;
// Render PDF page into canvas context
const renderContext = {
canvasContext: pdf.ctx,
viewport: viewport
};
const renderTask = page.render(renderContext);
// Wait for rendering to finish
renderTask.promise.then(() => {
pdf.pageRendering = false;
if (pdf.pageNumPending !== null) {
// New page rendering is pending
renderPage(pdf, pdf.pageNumPending);
pdf.pageNumPending = null;
}
})
.catch((error) => {
// TODO: track exception
});
});
}
function setPdfViewerMetaData(dotNetHelper, pdf) {
if (dotNetHelper == null)
return;
dotNetHelper.invokeMethodAsync('SetPdfViewerMetaData', { pagesCount: pdf.pagesCount, pageNumber: pdf.pageNum });
}