signature: fully working app with pdfjs-dist

This commit is contained in:
nobohan 2024-06-21 14:55:11 +02:00
parent 0f589ec57e
commit b0a8fd54a8
2 changed files with 44 additions and 39 deletions

View File

@ -53,12 +53,12 @@
"marked": "^12.0.2", "marked": "^12.0.2",
"masonry-layout": "^4.2.2", "masonry-layout": "^4.2.2",
"mime": "^4.0.0", "mime": "^4.0.0",
"pdfjs-dist": "^4.3.136",
"swagger-ui": "^4.15.5", "swagger-ui": "^4.15.5",
"vis-network": "^9.1.0", "vis-network": "^9.1.0",
"vue": "^3.2.37", "vue": "^3.2.37",
"vue-i18n": "^9.1.6", "vue-i18n": "^9.1.6",
"vue-multiselect": "3.0.0-alpha.2", "vue-multiselect": "3.0.0-alpha.2",
"vue-pdf-embed": "^2.0.4",
"vue-toast-notification": "^2.0", "vue-toast-notification": "^2.0",
"vuex": "^4.0.0" "vuex": "^4.0.0"
}, },

View File

@ -1,26 +1,25 @@
<template> <template>
<div> <div v-if="pageCount > 1">
<span> <button :disabled="page <= 1" @click="unTurnPage"></button>
<button :disabled="page <= 1" @click="unTurnPage"></button> {{ page }} / {{ pageCount }}
{{ page }} / {{ pageCount }} <button :disabled="page >= pageCount" @click="turnPage"></button>
<button :disabled="page >= pageCount" @click="turnPage"></button>
</span>
</div> </div>
<!-- <VuePdfEmbed :source="pdfSource" :page="page"/> -->
<canvas id="canvas"></canvas> <canvas id="canvas"></canvas>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref, Ref } from "vue"; import { ref, Ref } from "vue";
// import VuePdfEmbed from "vue-pdf-embed";
// import "vue-pdf-embed/dist/style/index.css";
import { SignatureZone } from "../../types"; import { SignatureZone } from "../../types";
import * as pdfjsLib from "pdfjs-dist"; import * as pdfjsLib from "pdfjs-dist";
import {
PDFDocumentProxy,
PDFPageProxy,
} from "pdfjs-dist/types/src/display/api";
// @ts-ignore // @ts-ignore
import * as PdfWorker from 'pdfjs-dist/build/pdf.worker.mjs'; import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs";
pdfjsLib.GlobalWorkerOptions.workerSrc = import.meta.url + 'pdfjs-dist/build/pdf.worker.mjs'; console.log(PdfWorker); // incredible but this is needed
console.log(PdfWorker) // incredible but this is needed
// import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs' // import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs'
// pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker; // pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker;
@ -29,10 +28,13 @@ import {
download_and_decrypt_doc, download_and_decrypt_doc,
} from "../StoredObjectButton/helpers"; } from "../StoredObjectButton/helpers";
pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs";
const page: Ref<number> = ref(1); const page: Ref<number> = ref(1);
const pageCount: Ref<number> = ref(3); //TODO get page count from PDF loaded, can be done with pdfjs (https://stackoverflow.com/questions/10253669/how-to-get-the-number-of-pages-of-a-pdf-uploaded-by-user) const pageCount: Ref<number> = ref(0);
let userSignatureZones = {} as SignatureZone; let userSignatureZones = {} as SignatureZone;
let pdfSource: Ref<string> = ref(""); let pdfSource: Ref<string> = ref("");
let pdf = {} as PDFDocumentProxy;
const signature = { const signature = {
id: 1, id: 1,
@ -86,31 +88,32 @@ const signature = {
const urlInfo = build_download_info_link(signature.storedObject.filename); const urlInfo = build_download_info_link(signature.storedObject.filename);
const showPdf = async (url: string) => { const mount_pdf = async (url: string) => {
const loadingTask = pdfjsLib.getDocument(url); const loadingTask = pdfjsLib.getDocument(url);
const pdf = await loadingTask.promise; pdf = await loadingTask.promise;
pageCount.value = pdf.numPages;
// Load information from the first page. await set_page(1);
const page = await pdf.getPage(1); };
const get_render_context = (pdfPage: PDFPageProxy) => {
const scale = 1; const scale = 1;
const viewport = page.getViewport({ scale }); const viewport = pdfPage.getViewport({ scale });
// Apply page dimensions to the `<canvas>` element.
const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement; const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement;
const context = canvas.getContext("2d") as CanvasRenderingContext2D; const context = canvas.getContext("2d") as CanvasRenderingContext2D;
canvas.height = viewport.height; canvas.height = viewport.height;
canvas.width = viewport.width; canvas.width = viewport.width;
// Render the page into the `<canvas>` element. return {
const renderContext = {
canvasContext: context, canvasContext: context,
viewport: viewport, viewport: viewport,
}; };
await page.render(renderContext);
console.log("Page rendered!");
}; };
const set_page = async (page: number) => {
const pdfPage = await pdf.getPage(page);
const renderContext = get_render_context(pdfPage);
await pdfPage.render(renderContext);
};
async function download_and_open(): Promise<Blob> { async function download_and_open(): Promise<Blob> {
let raw; let raw;
@ -120,12 +123,12 @@ async function download_and_open(): Promise<Blob> {
signature.storedObject.keyInfos, signature.storedObject.keyInfos,
new Uint8Array(signature.storedObject.iv) new Uint8Array(signature.storedObject.iv)
); );
await showPdf(URL.createObjectURL(raw));
init_pdf();
} catch (e) { } catch (e) {
console.error("error while downloading and decrypting document", e); console.error("error while downloading and decrypting document", e);
throw e; throw e;
} }
await mount_pdf(URL.createObjectURL(raw));
init_pdf();
return raw; return raw;
} }
@ -136,7 +139,7 @@ const init_pdf = () => {
(e: PointerEvent) => canvas_click(e), (e: PointerEvent) => canvas_click(e),
false false
); );
setTimeout(() => add_zones(), 200); setTimeout(() => add_zones(page.value), 800);
}; };
const canvas_click = (e: PointerEvent) => { const canvas_click = (e: PointerEvent) => {
@ -145,14 +148,16 @@ const canvas_click = (e: PointerEvent) => {
userSignatureZones = signature.zones[0]; //TODO for now, need another way to select a zone userSignatureZones = signature.zones[0]; //TODO for now, need another way to select a zone
}; };
const turnPage = () => { const turnPage = async () => {
page.value = page.value + 1; page.value = page.value + 1;
setTimeout(() => add_zones(), 200); await set_page(page.value);
setTimeout(() => add_zones(page.value), 200);
}; };
const unTurnPage = () => { const unTurnPage = async () => {
page.value = page.value - 1; page.value = page.value - 1;
setTimeout(() => add_zones(), 200); await set_page(page.value);
setTimeout(() => add_zones(page.value), 200);
}; };
const draw_zone = ( const draw_zone = (
@ -171,20 +176,20 @@ const draw_zone = (
); );
}; };
const add_zones = () => { const add_zones = (page: number) => {
const canvas = document.querySelectorAll("canvas")[0]; const canvas = document.querySelectorAll("canvas")[0];
const ctx = canvas.getContext("2d"); const ctx = canvas.getContext("2d");
if (ctx) { if (ctx) {
ctx.fillStyle = "green"; ctx.fillStyle = "green";
signature.zones.map((z) => { signature.zones
if (z.page === page.value) { .filter((z) => z.page === page)
draw_zone(z, ctx, canvas.width, canvas.height); .map((z) => draw_zone(z, ctx, canvas.width, canvas.height));
}
});
} }
}; };
download_and_open(); download_and_open();
</script> </script>
<style lang="scss"> <style lang="scss">