首页 > 解决方案 > 如何使用 PDF.js 和 jQuery 在 PDF 上创建可拖动元素

问题描述

我正在创建一项服务,使用 PDF.js 和 jQuery 用图像标记 pdf。我设法使用 PDF.js 创建了一个可拖动对象,但是该对象在被拖动时会留下过去对象的痕迹。

我曾经context.clearRect(0, 0, canvas.width, canvas.height);清除过去的对象,但它也清除了画布中的基础 PDF。

如何在不影响底层 PDF 的情况下拖动此对象?

这是我到目前为止所做的。

我正在使用以下代码将 PDF 加载到画布上。

function loadPdfPreview(base64pdf){

        pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.943/pdf.worker.min.js';

        var loadingTask = pdfjsLib.getDocument({data: base64pdf});

        loadingTask.promise.then(function (pdf) {

            // Fetch the first page
            pdf.getPage(1).then(function (page) {

                var scale = 1.0;

                var viewport = page.getViewport(scale);

                // Prepare canvas using PDF page dimensions
                canvas = document.getElementById('pdf-canvas');
                context = canvas.getContext('2d');

                canvas.height = viewport.height;
                canvas.width = viewport.width;

                canvasOffset = $("#pdf-canvas").offset();
                offsetX = canvasOffset.left;
                offsetY = canvasOffset.top;


                // Render PDF page into canvas context
                var renderContext = {
                    canvasContext: context,
                    viewport: viewport
                };

                page.render(renderContext).then(function () {

                    // creating the dummy object on success
                    drawObjectFromBlueprint(blueprint);

                }, function (e) {
                    console.log(e);
                });

            });
        });
    }

在将 pdf 加载到画布后,我使用以下函数在画布顶部绘制对象。

function drawObjectFromBlueprint(blueprint) {
        // drawing a draggable element inside the canvas
        context.strokeStyle = "lightgray";

        // Clearing the previous dummy objects
        context.clearRect(0, 0, canvas.width, canvas.height);

        // drawing the dummy object
        context.beginPath();
        context.moveTo(blueprint.x, blueprint.y);
        context.lineTo(blueprint.right, blueprint.y);
        context.lineTo(blueprint.right, blueprint.bottom);
        context.lineTo(blueprint.x, blueprint.bottom);
        context.closePath();

        context.fillStyle = blueprint.fill;
        context.fill();
        context.stroke();
    }

我使用以下代码处理鼠标移动事件。

function handleMouseMove(e) {

        var mouseX = parseInt(e.clientX - offsetX1);
        var mouseY = parseInt(e.clientY - offsetY1);

        // always update the global blueprint
        blueprint.x += (mouseX - lastX);
        blueprint.y += (mouseY - lastY);
        blueprint.right = blueprint.x + blueprint.width;
        blueprint.bottom = blueprint.y + blueprint.height;

        lastX = mouseX;
        lastY = mouseY;

        drawObjectFromBlueprint(blueprint);
    }

我使用以下代码监听鼠标移动事件。

$("#drawable-canvas").mousemove(function (e) {
        handleMouseMove(e);
    });

我想在不影响底层 PDF 的情况下重新绘制对象。试图通过清除整个画布来加载 PDF 并重新绘制对象,但它没有按预期工作。

标签: javascriptjquerypdfhtml5-canvaspdfjs

解决方案


在该page.render方法的回调中,会在画布上绘制pdf页面。您必须单独保存绘制的图像,以便原始图像不会因拖动而消失。

// maybe globalScope...?
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');

// your code

page.render(renderContext).then(function () {
  // Save the original page image.
  tempCanvas.width = canvas.width;
  tempCanvas.height = canvas.height;
  tempCtx.drawImage(canvas, 0, 0);

  // creating the dummy object on success
  drawObjectFromBlueprint(blueprint);
}, ...

接下来,请修改它以使用 中的原始页面图像进行绘制drawObjectFromBlueprint

function drawObjectFromBlueprint(blueprint) {
  // draw original page image
  context.drawImage(tempCanvas, 0, 0);

  // drawing a draggable element inside the canvas
  context.strokeStyle = "lightgray";
  ...
}


推荐阅读