mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
203 lines
5.5 KiB
Vue
203 lines
5.5 KiB
Vue
<template>
|
||
<div>
|
||
<button :disabled="!userSignatureZones" @click="confirm_sign">
|
||
Confirmer la signature
|
||
</button>
|
||
<button :disabled="!userSignatureZones" @click="undo_sign">
|
||
Supprimer la signature
|
||
</button>
|
||
</div>
|
||
<div v-if="pageCount > 1">
|
||
<button :disabled="page <= 1" @click="turn_page(-1)">❮</button>
|
||
{{ page }} / {{ pageCount }}
|
||
<button :disabled="page >= pageCount" @click="turn_page(1)">❯</button>
|
||
</div>
|
||
<canvas id="canvas"></canvas>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, Ref } from "vue";
|
||
import { Signature, SignatureZone } from "../../types";
|
||
import * as pdfjsLib from "pdfjs-dist";
|
||
import {
|
||
PDFDocumentProxy,
|
||
PDFPageProxy,
|
||
} from "pdfjs-dist/types/src/display/api";
|
||
|
||
// @ts-ignore
|
||
import * as PdfWorker from "pdfjs-dist/build/pdf.worker.mjs";
|
||
console.log(PdfWorker); // incredible but this is needed
|
||
|
||
// import { PdfWorker } from 'pdfjs-dist/build/pdf.worker.mjs'
|
||
// pdfjsLib.GlobalWorkerOptions.workerSrc = PdfWorker;
|
||
|
||
import {
|
||
build_download_info_link,
|
||
download_and_decrypt_doc,
|
||
} from "../StoredObjectButton/helpers";
|
||
|
||
pdfjsLib.GlobalWorkerOptions.workerSrc = "pdfjs-dist/build/pdf.worker.mjs";
|
||
|
||
const page: Ref<number> = ref(1);
|
||
const pageCount: Ref<number> = ref(0);
|
||
let userSignatureZones: Ref<null | SignatureZone> = ref(null);
|
||
let pdfSource: Ref<string> = ref("");
|
||
let pdf = {} as PDFDocumentProxy;
|
||
|
||
declare global {
|
||
interface Window {
|
||
signature: Signature;
|
||
}
|
||
}
|
||
|
||
const signature = window.signature;
|
||
const urlInfo = build_download_info_link(signature.storedObject.filename);
|
||
|
||
const mount_pdf = async (url: string) => {
|
||
const loadingTask = pdfjsLib.getDocument(url);
|
||
pdf = await loadingTask.promise;
|
||
pageCount.value = pdf.numPages;
|
||
await set_page(1);
|
||
};
|
||
|
||
const get_render_context = (pdfPage: PDFPageProxy) => {
|
||
const scale = 1;
|
||
const viewport = pdfPage.getViewport({ scale });
|
||
const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement;
|
||
const context = canvas.getContext("2d") as CanvasRenderingContext2D;
|
||
canvas.height = viewport.height;
|
||
canvas.width = viewport.width;
|
||
|
||
return {
|
||
canvasContext: context,
|
||
viewport: viewport,
|
||
};
|
||
};
|
||
|
||
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> {
|
||
let raw;
|
||
try {
|
||
raw = await download_and_decrypt_doc(
|
||
urlInfo,
|
||
signature.storedObject.keyInfos,
|
||
new Uint8Array(signature.storedObject.iv)
|
||
);
|
||
} catch (e) {
|
||
console.error("error while downloading and decrypting document", e);
|
||
throw e;
|
||
}
|
||
await mount_pdf(URL.createObjectURL(raw));
|
||
init_pdf();
|
||
return raw;
|
||
}
|
||
|
||
const init_pdf = () => {
|
||
const canvas = document.querySelectorAll("canvas")[0] as HTMLCanvasElement;
|
||
canvas.addEventListener(
|
||
"pointerup",
|
||
(e: PointerEvent) => canvas_click(e, canvas),
|
||
false
|
||
);
|
||
setTimeout(() => add_zones(page.value), 800);
|
||
};
|
||
|
||
const hit_signature = (
|
||
zone: SignatureZone,
|
||
xy: number[],
|
||
canvasWidth: number,
|
||
canvasHeight: number
|
||
) => {
|
||
const scaleXToCanvas = (x: number) => (x * canvasWidth) / zone.pageWidth;
|
||
const scaleYToCanvas = (y: number) => (y * canvasHeight) / zone.pageHeight;
|
||
return (
|
||
scaleXToCanvas(zone.x) < xy[0] &&
|
||
xy[0] < scaleXToCanvas(zone.x + zone.width) &&
|
||
scaleYToCanvas(zone.y) < xy[1] &&
|
||
xy[1] < scaleYToCanvas(zone.y + zone.height)
|
||
);
|
||
};
|
||
|
||
const canvas_click = (e: PointerEvent, canvas: HTMLCanvasElement) =>
|
||
signature.zones
|
||
.filter((z) => z.page === page.value)
|
||
.map((z) => {
|
||
if (
|
||
hit_signature(z, [e.offsetX, e.offsetY], canvas.width, canvas.height)
|
||
) {
|
||
const ctx = canvas.getContext("2d");
|
||
if (ctx) {
|
||
draw_zone(z, ctx, canvas.width, canvas.height, true);
|
||
}
|
||
userSignatureZones.value = z;
|
||
}
|
||
});
|
||
|
||
const turn_page = async (upOrDown: number) => {
|
||
userSignatureZones.value = null;
|
||
page.value = page.value + upOrDown;
|
||
await set_page(page.value);
|
||
setTimeout(() => add_zones(page.value), 200);
|
||
};
|
||
|
||
const draw_zone = (
|
||
zone: SignatureZone,
|
||
ctx: CanvasRenderingContext2D,
|
||
canvasWidth: number,
|
||
canvasHeight: number,
|
||
selected = false,
|
||
) => {
|
||
const scaleXToCanvas = (x: number) =>
|
||
Math.round((x * canvasWidth) / zone.pageWidth);
|
||
const scaleYToCanvas = (y: number) =>
|
||
Math.round((y * canvasHeight) / zone.pageHeight);
|
||
ctx.strokeStyle = selected ? "orange " : "yellow";
|
||
ctx.lineWidth = 10;
|
||
ctx.lineJoin = "bevel";
|
||
ctx.strokeRect(
|
||
scaleXToCanvas(zone.x),
|
||
scaleYToCanvas(zone.y),
|
||
scaleXToCanvas(zone.width),
|
||
scaleYToCanvas(zone.height)
|
||
);
|
||
};
|
||
|
||
const add_zones = (page: number) => {
|
||
const canvas = document.querySelectorAll("canvas")[0];
|
||
const ctx = canvas.getContext("2d");
|
||
if (ctx) {
|
||
signature.zones
|
||
.filter((z) => z.page === page)
|
||
.map((z) => draw_zone(z, ctx, canvas.width, canvas.height));
|
||
}
|
||
};
|
||
|
||
const confirm_sign = () => {
|
||
console.log(userSignatureZones.value);
|
||
//TODO POST userSignatureZones to backend
|
||
};
|
||
|
||
const undo_sign = async () => {
|
||
const canvas = document.querySelectorAll("canvas")[0];
|
||
const ctx = canvas.getContext("2d");
|
||
if (ctx && userSignatureZones.value) {
|
||
draw_zone(userSignatureZones.value, ctx, canvas.width, canvas.height);
|
||
//another option is to reload the canvas
|
||
//await set_page(page.value);
|
||
//setTimeout(() => add_zones(page.value), 200);
|
||
}
|
||
userSignatureZones.value = null;
|
||
};
|
||
|
||
download_and_open();
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
</style>
|
||
|