使用 pdf.js 使用加载的 pdf 文件在 canvas 中绘制矩形
Draw rectangle in canvas with loaded pdf file using pdf.js
我正在尝试在 pdf 文件上绘制矩形。当我在 pdf 中绘制矩形时,矩形无法正确绘制。
我想一次只画一个矩形,当我画新的矩形时,旧的矩形应该被移除,但它没有发生。
这是我的代码:
pdf渲染代码(渲染正常)
function pdfFile (file) {
pdfjsLib.workerSrc = 'pdf.worker.js';
pdfjsLib.getDocument(file).promise.then(function(pdfDoc) {
pdf = pdfDoc;
document.getElementById('page_count').textContent = pdfDoc.numPages;
showButtonGroup(pdf);
renderPage(pageNum);
});
}
function renderPage(num) {
pageRendering = true;
pdf.getPage(num).then(function(page) {
var viewport = page.getViewport({scale: scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function() {
pageRendering = false;
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
document.getElementById('page_num').textContent = num;
}
鼠标移动功能无法正常使用
function mouseMove(e) {
if (drag) {
ctx.putImageData(pdfPages[pageNum], 0, 0);
ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
rect.w = ((e.pageX - x) - this.offsetLeft) - rect.startX;
rect.h = ((e.pageY - y) - this.offsetTop) - rect.startY;
ctx.strokeStyle = color;
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
Object.assign(data, {
x: rect.startX,
y: rect.startY,
w: rect.w,
h: rect.h
})
console.log(data);
}
}
注
当我启用 clearRect 和 putImageData 函数时,矩形会正确绘制,但 canvas pdf 显示为空。这是附件图片
当仅启用clearRect 功能时,在pdf 中显示多个矩形。这是附件图片
请检查以下内容,需要在创建新矩形之前清除现有矩形
function renderPage(num) {
pageRendering = true;
pdf.getPage(num).then(function (page) {
var viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
pageRendering = false;
//You need to clear the existing rectangle
pdfPages[num] = ctx.getImageData(0, 0, canvas.width, canvas.height);
//Now you can draw new rectangle
drawRectangle(10, 10, 100, 50);
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
function drawRectangle(x, y, w, h) {
ctx.strokeStyle = color;
ctx.strokeRect(x, y, w, h);
}
使用 pdf.js 在 canvas 上做可选矩形的另一种方法是使用 toDataURL() 保存原始 canvas,然后在 clearRect 之后使用 canvas.draw () 使用之前保存的 base64 图像绘制 canvas。
import React, { useEffect, useState, useRef, useCallback } from "react";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
import * as pdfjsLib from "pdfjs-dist/build/pdf";
export default function CustomPdfReader({ url }) {
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
const canvasRef = useRef();
const [pdfRef, setPdfRef] = useState("");
const currentPage = 1;
const zoomScale = 1;
const rotateAngle = 0;
var pdf_image = "";
const renderPage = useCallback(
(pageNum, pdf = pdfRef) => {
pdf &&
pdf.getPage(pageNum).then(function (page) {
const viewport = page.getViewport({ scale: zoomScale, rotation: rotateAngle });
const canvas = canvasRef.current;
canvas.height = viewport?.height;
canvas.width = viewport?.width;
const renderContext = {
canvasContext: canvas?.getContext("2d"),
viewport: viewport,
textContent: pdfRef,
};
page.render(renderContext);
});
},
[pdfRef, url]
);
useEffect(() => {
if (url.slice(-4).toLowerCase() === ".pdf") {
renderPage(currentPage, pdfRef);
} else {
setPdfRef("");
}
}, [pdfRef, renderPage, url]);
useEffect(() => {
const loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(
(loadedPdf) => {
setPdfRef(loadedPdf);
},
function (reason) {
console.error(reason);
}
);
}, [url]);
var cursorInCanvas = false;
var canvasOfDoc = canvasRef?.current;
var ctx;
var startX;
var startY;
var offsetX;
var offsetY;
const saveInitialCanvas = () => {
if (canvasOfDoc?.getContext) {
var canvasPic = new Image();
canvasPic.src = canvasOfDoc.toDataURL();
pdf_image = canvasPic;
}
};
useEffect(() => {
if (canvasOfDoc) {
ctx = canvasOfDoc.getContext("2d");
var canvasOffset = canvasOfDoc.getBoundingClientRect();
offsetX = canvasOffset.left;
offsetY = canvasOffset.top;
}
}, [canvasOfDoc, pdfRef, renderPage, url]);
function handleMouseIn(e) {
if (typeof pdf_image == "string") {
saveInitialCanvas();
}
e.preventDefault();
e.stopPropagation();
startX = ((e.offsetX * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
startY = ((e.offsetY * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
cursorInCanvas = true;
}
function handleMouseOut(e) {
e.preventDefault();
e.stopPropagation();
cursorInCanvas = false;
}
function handleMouseMove(e) {
e.preventDefault();
e.stopPropagation();
if (!cursorInCanvas) {
return;
}
let mouseX = ((e.offsetX * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
let mouseY = ((e.offsetY * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
var width = mouseX - startX;
var height = mouseY - startY;
if (ctx) {
ctx?.clearRect(0, 0, canvasOfDoc.width, canvasOfDoc.height);
ctx?.drawImage(pdf_image, 0, 0);
ctx.beginPath();
ctx.rect(startX, startY, width, height);
ctx.strokeStyle = "#1B9AFF";
ctx.lineWidth = 1;
ctx.stroke();
}
}
canvasOfDoc?.addEventListener("mousedown", function (e) {
handleMouseIn(e);
});
canvasOfDoc?.addEventListener("mousemove", function (e) {
handleMouseMove(e);
});
canvasOfDoc?.addEventListener("mouseup", function (e) {
handleMouseOut(e);
});
canvasOfDoc?.addEventListener("mouseout", function (e) {
handleMouseOut(e);
});
return (
<>
<canvas id="pdf-doc" ref={canvasRef} />
</>
);
}
我正在尝试在 pdf 文件上绘制矩形。当我在 pdf 中绘制矩形时,矩形无法正确绘制。
我想一次只画一个矩形,当我画新的矩形时,旧的矩形应该被移除,但它没有发生。
这是我的代码:
pdf渲染代码(渲染正常)
function pdfFile (file) {
pdfjsLib.workerSrc = 'pdf.worker.js';
pdfjsLib.getDocument(file).promise.then(function(pdfDoc) {
pdf = pdfDoc;
document.getElementById('page_count').textContent = pdfDoc.numPages;
showButtonGroup(pdf);
renderPage(pageNum);
});
}
function renderPage(num) {
pageRendering = true;
pdf.getPage(num).then(function(page) {
var viewport = page.getViewport({scale: scale});
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function() {
pageRendering = false;
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
document.getElementById('page_num').textContent = num;
}
鼠标移动功能无法正常使用
function mouseMove(e) {
if (drag) {
ctx.putImageData(pdfPages[pageNum], 0, 0);
ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
rect.w = ((e.pageX - x) - this.offsetLeft) - rect.startX;
rect.h = ((e.pageY - y) - this.offsetTop) - rect.startY;
ctx.strokeStyle = color;
ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h);
Object.assign(data, {
x: rect.startX,
y: rect.startY,
w: rect.w,
h: rect.h
})
console.log(data);
}
}
注
当我启用 clearRect 和 putImageData 函数时,矩形会正确绘制,但 canvas pdf 显示为空。这是附件图片
当仅启用clearRect 功能时,在pdf 中显示多个矩形。这是附件图片
请检查以下内容,需要在创建新矩形之前清除现有矩形
function renderPage(num) {
pageRendering = true;
pdf.getPage(num).then(function (page) {
var viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
pageRendering = false;
//You need to clear the existing rectangle
pdfPages[num] = ctx.getImageData(0, 0, canvas.width, canvas.height);
//Now you can draw new rectangle
drawRectangle(10, 10, 100, 50);
if (pageNumPending !== null) {
renderPage(pageNumPending);
pageNumPending = null;
}
});
});
function drawRectangle(x, y, w, h) {
ctx.strokeStyle = color;
ctx.strokeRect(x, y, w, h);
}
使用 pdf.js 在 canvas 上做可选矩形的另一种方法是使用 toDataURL() 保存原始 canvas,然后在 clearRect 之后使用 canvas.draw () 使用之前保存的 base64 图像绘制 canvas。
import React, { useEffect, useState, useRef, useCallback } from "react";
import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
import * as pdfjsLib from "pdfjs-dist/build/pdf";
export default function CustomPdfReader({ url }) {
pdfjsLib.GlobalWorkerOptions.workerSrc = pdfjsWorker;
const canvasRef = useRef();
const [pdfRef, setPdfRef] = useState("");
const currentPage = 1;
const zoomScale = 1;
const rotateAngle = 0;
var pdf_image = "";
const renderPage = useCallback(
(pageNum, pdf = pdfRef) => {
pdf &&
pdf.getPage(pageNum).then(function (page) {
const viewport = page.getViewport({ scale: zoomScale, rotation: rotateAngle });
const canvas = canvasRef.current;
canvas.height = viewport?.height;
canvas.width = viewport?.width;
const renderContext = {
canvasContext: canvas?.getContext("2d"),
viewport: viewport,
textContent: pdfRef,
};
page.render(renderContext);
});
},
[pdfRef, url]
);
useEffect(() => {
if (url.slice(-4).toLowerCase() === ".pdf") {
renderPage(currentPage, pdfRef);
} else {
setPdfRef("");
}
}, [pdfRef, renderPage, url]);
useEffect(() => {
const loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(
(loadedPdf) => {
setPdfRef(loadedPdf);
},
function (reason) {
console.error(reason);
}
);
}, [url]);
var cursorInCanvas = false;
var canvasOfDoc = canvasRef?.current;
var ctx;
var startX;
var startY;
var offsetX;
var offsetY;
const saveInitialCanvas = () => {
if (canvasOfDoc?.getContext) {
var canvasPic = new Image();
canvasPic.src = canvasOfDoc.toDataURL();
pdf_image = canvasPic;
}
};
useEffect(() => {
if (canvasOfDoc) {
ctx = canvasOfDoc.getContext("2d");
var canvasOffset = canvasOfDoc.getBoundingClientRect();
offsetX = canvasOffset.left;
offsetY = canvasOffset.top;
}
}, [canvasOfDoc, pdfRef, renderPage, url]);
function handleMouseIn(e) {
if (typeof pdf_image == "string") {
saveInitialCanvas();
}
e.preventDefault();
e.stopPropagation();
startX = ((e.offsetX * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
startY = ((e.offsetY * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
cursorInCanvas = true;
}
function handleMouseOut(e) {
e.preventDefault();
e.stopPropagation();
cursorInCanvas = false;
}
function handleMouseMove(e) {
e.preventDefault();
e.stopPropagation();
if (!cursorInCanvas) {
return;
}
let mouseX = ((e.offsetX * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
let mouseY = ((e.offsetY * canvasOfDoc.width) / canvasOfDoc.clientWidth) | 0;
var width = mouseX - startX;
var height = mouseY - startY;
if (ctx) {
ctx?.clearRect(0, 0, canvasOfDoc.width, canvasOfDoc.height);
ctx?.drawImage(pdf_image, 0, 0);
ctx.beginPath();
ctx.rect(startX, startY, width, height);
ctx.strokeStyle = "#1B9AFF";
ctx.lineWidth = 1;
ctx.stroke();
}
}
canvasOfDoc?.addEventListener("mousedown", function (e) {
handleMouseIn(e);
});
canvasOfDoc?.addEventListener("mousemove", function (e) {
handleMouseMove(e);
});
canvasOfDoc?.addEventListener("mouseup", function (e) {
handleMouseOut(e);
});
canvasOfDoc?.addEventListener("mouseout", function (e) {
handleMouseOut(e);
});
return (
<>
<canvas id="pdf-doc" ref={canvasRef} />
</>
);
}