wojtekmaj / react-pdf

Display PDFs in your React app as easily as if they were images.
https://projects.wojtekmaj.pl/react-pdf
MIT License
9.24k stars 877 forks source link

Cannot render all pages vertically #1605

Closed FrancescoSaverioZuppichini closed 12 months ago

FrancescoSaverioZuppichini commented 1 year ago

Before you start - checklist

Description

Hi there,

I am trying to use pdfjs inside this package and render all the pages from a pdf vertically in the same canvas

  const doRender = async () => {
    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");

    const loadingTask = pdfjs.getDocument(pdfPath);
    const pdf = await loadingTask.promise;

    let totalHeight = 2000;
    let maxWidth = 800;
    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
      const page = await pdf.getPage(pageNum);
      const viewport = page.getViewport({ scale: pdfScale });
      totalHeight += viewport.height;
      maxWidth = Math.max(maxWidth, viewport.width);
    }

    canvas.width = maxWidth + noteSpaceWidth;
    canvas.height = totalHeight;

    totalHeight = 0;

    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
      const page = await pdf.getPage(pageNum);
      const viewport = page.getViewport({ scale: pdfScale });
      const transform = [1, 0, 0, 1, 0, totalHeight];

      await page.render({
        canvasContext: context,
        viewport,
        transform,
      }).promise;

      totalHeight += viewport.height;
    }

    context.fillStyle = "#ffffff";
    context.fillRect(maxWidth, 0, noteSpaceWidth, totalHeight);
  };

However, I can see the pages in the right place for half a second and then they are all gone and only the last one is visible.

Thanks a lot,

Fra

Steps to reproduce

You can run this react file, change the pdf path

"use client";
import React, { useEffect, useRef, useState } from "react";
import { pdfjs } from "react-pdf";

pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.js",
  import.meta.url
).toString();

const noteSpaceWidth = 100;
function PDFCanvas() {
  const pdfPath = "1512.03385.pdf";

  const canvasRef = useRef<HTMLCanvasElement | null>(null);
  const [isDrawing, setIsDrawing] = useState(false);
  const [pdfScale, setPdfScale] = useState(1.0);
  const [width, setWidth] = useState(500);
  const [height, setHeight] = useState(500);

  //   useEffect(() => {
  //     const canvas = canvasRef.current;
  //     const context = canvas.getContext("2d");
  //     context.fillStyle = "#ffffff";
  //     context.fillRect(0, 0, canvas.width, canvas.height);
  //   }, [width, height]);

  const doRender = async () => {
    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");

    const loadingTask = pdfjs.getDocument(pdfPath);
    const pdf = await loadingTask.promise;

    let totalHeight = 2000;
    let maxWidth = 800;
    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
      const page = await pdf.getPage(pageNum);
      const viewport = page.getViewport({ scale: pdfScale });
      totalHeight += viewport.height;
      maxWidth = Math.max(maxWidth, viewport.width);
    }

    canvas.width = maxWidth + noteSpaceWidth;
    canvas.height = totalHeight;

    totalHeight = 0;

    for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
      const page = await pdf.getPage(pageNum);
      const viewport = page.getViewport({ scale: pdfScale });
      const transform = [1, 0, 0, 1, 0, totalHeight];

      await page.render({
        canvasContext: context,
        viewport,
        transform,
      }).promise;

      totalHeight += viewport.height;
    }

    context.fillStyle = "#ffffff";
    context.fillRect(maxWidth, 0, noteSpaceWidth, totalHeight);
  };

  useEffect(() => {
    const canvas = canvasRef.current;
    if (!canvas) return;
    doRender();
  }, [pdfScale]);

  // Handlers for drawing on the canvas
  const handleMouseDown = () => {
    setIsDrawing(true);
  };

  const handleMouseMove = (event: React.MouseEvent) => {
    if (!isDrawing) return;

    const canvas = canvasRef.current;
    if (!canvas) return;
    const context = canvas.getContext("2d");
    const rect = canvas.getBoundingClientRect();
    const x = event.clientX - rect.left;
    const y = event.clientY - rect.top;

    context.lineWidth = 2;
    context.lineCap = "round";
    context.strokeStyle = "black";

    context.lineTo(x, y);
    context.stroke();
    context.beginPath();
    context.moveTo(x, y);
  };

  const handleMouseUp = () => {
    if (!isDrawing) return;

    const canvas = canvasRef.current;
    const context = canvas.getContext("2d");

    context.beginPath();
    setIsDrawing(false);
  };

  return (
    <div>
      {/* <button onClick={() => setPdfScale((prev) => prev + 0.1)}>Zoom In</button>
      <button onClick={() => setPdfScale((prev) => prev - 0.1)}>
        Zoom Out
      </button> */}
      <canvas
        ref={canvasRef}
        width={width}
        height={height}
        style={{ border: "1px solid #000", position: "relative" }}
        // onMouseDown={handleMouseDown}
        // onMouseMove={handleMouseMove}
        // onMouseUp={handleMouseUp}
        // onMouseLeave={handleMouseUp}
      />
      {/* <div
        style={{
          position: "absolute",
          width: "10px",
          height: "10px",
          backgroundColor: "red",
          top: height - 5,
          left: width - 5,
          cursor: "se-resize",
        }}
        onMouseDown={handleMouseDown}
      /> */}
    </div>
  );
}

Expected behavior

I woudl expect to see all the pages

Actual behavior

Only the last one is there, I can see the others for a fraction of a second in the right place

Additional information

No response

Environment

wojtekmaj commented 12 months ago

You're essentially using pure pdfjs which makes no sense - you could use pdfjs-dist directly, and you would probably be happier dev as a result - you'd get the latest and greatest version available.

As it's unrelated to anything I've built on top of PDF.js I'll not be able to provide help. I suggest asking in PDF.js repo instead. Sorry!

FrancescoSaverioZuppichini commented 11 months ago

Thanks, could you provide an example in rendering all the pages of a pdf in a canvas using whatever you see fit?