Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview doesn't take x coordinate into account #2

Open
MortenHannemose opened this issue Nov 18, 2022 · 3 comments
Open

Preview doesn't take x coordinate into account #2

MortenHannemose opened this issue Nov 18, 2022 · 3 comments

Comments

@MortenHannemose
Copy link

Thank you for writing this code. I was looking for something exactly like this.
When I mouse over a reference that's on the right side of the page, it still shows the entire page (unlike in the preview gif you have, where it only shows the right part of the page). If I zoom in and click the link, I'm taken to the correct place in both x and y.
image
For reference the PDF is https://arxiv.org/pdf/1711.07971.pdf and I'm on Firefox 107.0 (latest version as of this post)
Another difference to your gif is that the top left corner of the preview does not coincide with the mouse location. In both cases, the gif is the more desirable behavior.

@belinghy
Copy link
Owner

belinghy commented Nov 21, 2022

Thanks! Glad you found it useful.

To have the behaviour you described, use the bookmarklet below. For reference, if others want to make adjust the code to their preferences, the code below is a few lines change from the default behaviour here and here.

javascript:(async () => {
  const app = window.PDFViewerApplication;
  const anchor = document.getElementById("viewer");
  if ("_previewHandler" in app) {
    anchor.removeEventListener("mouseover", app._previewHandler);
    delete app._previewHandler;
    delete app._previewing;
    return;
  }

  const box = anchor.getBoundingClientRect();
  const halfWidth = (box.left + box.right) / 2;
  const destinations = await app.pdfDocument.getDestinations();
  app._previewing = false;

  async function mouseoverHandler(event) {
    if (event.target.className != "internalLink" || app._previewing) return;

    const hash = event.target.hash;
    const parent = event.target.parentElement;

    const preview = document.createElement("canvas");
    const previewStyle = preview.style;
    previewStyle.border = "1px solid black";
    previewStyle.direction = "ltr";
    previewStyle.position = "fixed";
    previewStyle.zIndex = "2";
    previewStyle.top = `${event.clientY + 4}px`;
    previewStyle.boxShadow = "5px 5px 5px black, -5px 5px 5px black";

    const namedDest = decodeURIComponent(hash.substring(1));
    const explicitDest =
      namedDest in destinations
        ? destinations[namedDest]
        : JSON.parse(namedDest);
    const pageNumber = app.pdfLinkService._cachedPageNumber(explicitDest[0]);

    app.pdfDocument.getPage(pageNumber).then(function (page) {
      const tempViewport = page.getViewport({ scale: 1.0 });
      const height = tempViewport.height * 1.2 * app.pdfViewer.currentScale;
      const width = tempViewport.width * 1.2 * app.pdfViewer.currentScale;
      previewStyle.height = `${height}px`;
      previewStyle.width = `${width}px`;
      previewStyle.left = `${event.clientX - 4}px`;

      let offsetX, offsetY;
      switch (explicitDest[1].name) {
        case "XYZ":
          offsetX = -explicitDest[2];
          offsetY = explicitDest[3];
          break;
        case "FitH":
        case "FitBH":
        case "FitV":
        case "FitBV":
          offsetY = explicitDest[2];
          break;
        default:
          console.log(`Oops, link ${explicitDest[1].name} is not supported.`);
      }

      const scale = 4;
      const viewport = page.getViewport({
        scale: scale,
        offsetX: offsetX * scale,
        offsetY: (offsetY - tempViewport.height) * scale,
      });

      preview.height = viewport.height;
      preview.width = viewport.width;

      const renderContext = {
        canvasContext: preview.getContext("2d"),
        viewport: viewport,
      };
      page.render(renderContext);
    });

    anchor.prepend(preview);
    app._previewing = true;

    parent.addEventListener("mouseleave", function (event) {
      preview.remove();
      app._previewing = false;
    });
  }
  anchor.addEventListener("mouseover", mouseoverHandler);
  app._previewHandler = mouseoverHandler;
})();

@MortenHannemose
Copy link
Author

Ah, perfect. Thanks so much for sharing this. It's also much easier to edit the not minified code 😄
I also have a minor comment/something I was wondering. It seems that FitH and FitBH are the only modes that can specify a y-offset, and that if FitV and FitBV specify an offset, it's an offset in the x-direction. However, I've not encountered them in a real PDF, so this is only based on what I've read in the documentation.

@MortenHannemose
Copy link
Author

And increasing the zIndex to a large value such as 99 is necessary for some PDFs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants