Search code examples
javascriptvue.jspdf.js

How do I use pdfjs with vue3 and vite?


I'm trying to convert my vue2 app to vue3 with Vite. Because there's no webpack, my pdfjs implementation broke. I'm able to render the pdf but renderTextLayer isn't working correctly (see image below).

enter image description here

Here is the message in the browser:

Warning: Setting up fake worker.

Warning: fetchStandardFontData: failed to fetch file "FoxitSymbol.pfb" with "UnknownErrorException: StandardFontDataFactory not initialized, see the useWorkerFetch parameter.".

Warning: fetchStandardFontData: failed to fetch file "FoxitDingbats.pfb" with "UnknownErrorException: StandardFontDataFactory not initialized, see the useWorkerFetch parameter.".

I'm not quite sure how to fix the worker. I've tried adding the worker suffix to the import as shown here but I get the following error and it won't even render the pdf.

Error: Setting up fake worker failed: "Cannot convert object to primitive value".

Not sure why standardFontDataFactory isn't initialized.

  • vue: 3.2.25
  • pdfjs-dist: 2.16.105

<script>
  const pdfjs = await import('pdfjs-dist/build/pdf');
  const pdfjsWorker = await import('pdfjs-dist/build/pdf.worker.entry');
  import { renderTextLayer, getDocument } from "pdfjs-dist";
  pdfjs.GlobalWorkerOptions.workerSrc = pdfjsWorker

  export default {
    async mounted() {
      let that=this
      let loadingTask = getDocument(this.$store.getters.blobURL)
      loadingTask.promise.then((pdf) => {
        for (const pageNumber of [...Array(pdf.numPages).keys()]){
          pdf.getPage(pageNumber+1).then(function(page) {
            var scale = 1.5;
            var viewport = page.getViewport({scale: scale});
            var canvas = document.getElementById(`pdfPage${pageNumber+1}`);
            var context = canvas.getContext('2d');
            canvas.height = viewport.height
            canvas.width = viewport.width

            var renderContext = {
              canvasContext: context,
              viewport: viewport
            };
            var renderTask = page.render(renderContext);
            renderTask.promise.then(function () {
              that.createTextLayer(page,canvas)           
            })
          })
        }

      })

    }
    methods: {
      createTextLayer(page,canvas){
        page.getTextContent().then(content => {
          let textLayerDiv=document.getElementById('textLayer'+page.pageNumber) 
          let rect = canvas.getBoundingClientRect()
          textLayerDiv.style.top=`${rect.top}px`
          let scale = rect.height / page.getViewport(1).height
          let viewport = page.getViewport(scale)
          renderTextLayer({ 
            textContent: content,
            container: textLayerDiv,
            viewport,
            textDivs:[] 
          })
        })  
      },
    }
   }
</script>


Solution

  • I found out the issue was scoped CSS. Since the element renders later, the scoped CSS wasn't getting applied. Below is the imported css that needs to be in an unscoped style tag.

    @import '../../node_modules/pdfjs-dist/web/pdf_viewer.css';