javascriptvue.jspdf.js

pdf.js pdfViewer float number rouding error


I am using pdf.js's pdfviewer class.

When I try to render the pdf with text layer, it always complains

The --scale-factor css variable must be set, to the same value as viewport.scale, either on the container-element itself or higher up in the DOM.

I have set the variable. But the error won't go away. So I set breakpoint to see what's happenning.

if (
  visibility === "visible" &&
  (!scaleFactor || Math.abs(scaleFactor - viewport.scale) > 1e-15)
) {
  console.error(
    "The `--scale-factor` CSS-variable must be set, " +
      "to the same value as `viewport.scale`, " +
      "either on the `container`-element itself or higher up in the DOM."
  );
}

This is the code that throws error. scaleFactor was 1.3333, and viewport.scale was 1.3333333333333333. The pdf is 4:3 ratio. Clearly this difference in precision causes the error.

This is the code I wrote

<template>
  <div>
    <div ref="viewerContainer" class="container" style="position: absolute;" :style="{'--scale-factor': scale}" >
      <div ref="pdfViewer"></div>
    </div>
    <button @click="loadPDF">Load PDF</button>
  </div>
</template>

<script>
import { PDFViewer, EventBus } from "pdfjs-dist/web/pdf_viewer";
import * as pdfjsLib from "pdfjs-dist/build/pdf";
pdfjsLib.GlobalWorkerOptions.workerSrc =
  "https://cdn.jsdelivr.net/npm/pdfjs-dist@3.5.141/build/pdf.worker.min.js";
import { isProxy, toRaw } from 'vue';

export default {
  data() {
    return {
      pdfViewer: null,
      pdfUrl: "./sample.pdf",
      scale: 2,
    };
  },
  mounted() {
    this.initializePDFViewer();
  },
  methods: {
    initializePDFViewer() {
      const container = this.$refs.viewerContainer;
      const viewer = this.$refs.viewer;

      this.pdfViewer = new PDFViewer({
        container: container,
        viewer: viewer,
        eventBus: new EventBus(),
        textLayerMode: 2,
      });
    },
    loadPDF() {
      // Load PDF and render it in the PDFViewer
      const loadingTask = pdfjsLib.getDocument(this.pdfUrl);
      loadingTask.promise.then((pdfDocument) => {
        if (isProxy(this.pdfViewer)){
          toRaw(this.pdfViewer).setDocument(pdfDocument)
        }
      });
    },
  },
};
</script>

<style scoped>
.pdfViewer {
  width: 100%; /* or specify the desired width */
  height: 100%; /* or specify the desired height */
}
</style>

Please advise on how to prevent such a problem.

The version of pdfjs I am using is 3.5.141.


Solution

  • https://github.com/mozilla/pdf.js/pull/16256

    Here's a pull request from last week. It fixed the bug introduced in 3.5.141, happening on chromium browser.

    They merged the pull request. However, a new version is not yet released.

    I can confirm the bug didn't exist in previous verion, 3.4.120.

    So, there are three options.

    1. Don't use pdfViewer yet, render it manually.
    2. Revert to previous version, 3.4.120.
    3. Compile from source.