I'm using PDF JS in a Vue3 project and I want to overlay a <canvas id="draw_canvas">
on the rendered pdf document. Thus, allowing me to programmatically draw rectangles over the pdf document as an attempt to place a marker on certain places.
The way PDF JS renders a pdf file is by placing the content of each page inside individual <canvas>
elements. I have 2 Vue SFCs called App
and Child
. The Child
component loads and renders the pages of the pdf document (3 pages) inside a <div id="pages_container">
. This div
is enclosed inside another one, <div id="doc_container">
, which is made scrollable.
To adjust the height of <canvas id="draw_canvas">
whenever <div id="pages_container">
grows, I'm using a ResizeObserver
. This observes the <div id="pages_container">
for changes in size and then adjusts the height of the <canvas id="draw_canvas">
to match its offsetHeight
.
// Child.vue
<script setup>
import { onMounted } from 'vue';
// function to load pdf file and render its pages
const loadDoc = () => {
pdfjsLib.getDocument("doc.pdf").promise.then((pdfDoc) => {
const pageCount = pdfDoc._pdfInfo.numPages;
for (let i = 1; i <= pageCount; i++) {
pdfDoc.getPage(i)
.then((page) => {
// get the viewport object of the page in the pdf
const viewport = page.getViewport({ scale: 1.25, });
// create a new canvas to place the content of this page
const newPageCanvas = document.createElement("canvas");
newPageCanvas.setAttribute("id", "page_" + i);
newPageCanvas.setAttribute("class", "pdf-page-canvas");
newPageCanvas.width = viewport.width;
newPageCanvas.height = viewport.height;
// add the page canvas to the DOM
document.getElementById("pages_container").appendChild(newPageCanvas);
// render page
const renderContext = {
canvasContext: newPageCanvas.getContext("2d"),
viewport: viewport
};
page.render(renderContext);
});
}
});
}
// function to place a marker on the pdf document
const placeBox = (x, y, width, height) => {
console.log("Draw box with attributes: ", x, y, width, height);
const drawCanvasContext = document.querySelector("#draw_canvas").getContext("2d");
drawCanvasContext.strokeStyle = "red";
drawCanvasContext.strokeRect(x, y, width, height);
}
defineExpose({placeBox,});
onMounted(() => {
loadDoc();
const observer = new ResizeObserver(entries => {
console.log("Height changed!");
const drawCanvas = document.querySelector("#draw_canvas");
const offsetHeight = document.querySelector("#pages_container").offsetHeight;
console.log(`Div offset height: ${offsetHeight}`);
console.log(`Canvas old height: ${drawCanvas.height}`);
drawCanvas.height = offsetHeight;
console.log(`canvas new height: ${drawCanvas.height}`);
});
observer.observe(document.querySelector("#pages_container"));
});
</script>
<template>
<div id="doc_container">
<div id="pages_container">
<!-- the canvases that contain the pdf pages will be placed in here -->
</div>
<canvas id="draw_canvas"></canvas>
</div>
</template>
<style scoped>
#doc_container {
position: relative;
width: 100%;
height: 100vh;
overflow-y: scroll;
border: 1px solid green;
}
#pages_container {
border: 2px dashed red;
}
#draw_canvas {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
background-color: gray;
opacity: 0.6;
}
</style>
By printing out the offsetHeight
of <div id="pages_container">
whenever changed, I noted the max height it grows to is 3171px. So, the max height <canvas id="draw_canvas">
must also be 3171px, but it is not. It appears to be exceeding that value.
I have given the <div id="pages_container">
a dashed red border and the <canvas id="drawCanvas">
a gray background colour with an opacity of 0.6. In the screenshot above, we can see that the canvas exceed the div in height. I don't understand why. How do I adjust the height of this canvas so that it matches the height of <div id="pages_container">
?
from How to dynamically adjust the dimensions of a canvas based on the content inside a scrollable div?
No comments:
Post a Comment