20 Nov 2018

Fast PDF Viewing/Markup inside Forge Viewer

GITHUB: https://github.com/wallabyway/offline-pdf-markup

Viewing PDF's through Forge services has always been "tricky"... until now !!!

The BIM360 team have come up with Fast Native PDF rendering inside Forge Viewer.

 

Try a LIVE DEMO here:  https://wallabyway.github.io/offline-pdf-markup/

 

Some background:

Originally, Forge Viewer tried converting PDF into F2D (by converting PDF to DWF and then sending it through Model Derivative Services, which produces the F2D vector file).  This was not very elegant.

Then, the second approach was to... "just let the browser handle it".   A360 used PDF.js to decode and render the PDF, but the rendering was a bit too slow.  The other option was to pass the PDF directly to the OS and let, whatever PDF viewer was available, handle it (ie. Adobe Acrobat Reader etc), but the rendered output wasn't consistent from one computer to the next.

Thankfully, the BIM360 team came up with a cool hybrid approach.  By using the decoding part of PDF.js and then using the Forge Viewer's fast 2D vector webGL renderer, they now can quickly render large PDF's, right inside the Forge Viewer.  

And since it's built into Forge Viewer, you get to use all the other handy extensions Forge offers, like...

1. Measure with snapping to Edges and Corners

2. Markup with callouts and text

3. Offline viewing (or disconnected)

All three of these features are shown in the demo link above.

Check out the PDF vector rendering performance here

 

 

Viewing your own PDF:

  1. Initialize the viewer as you normally would for a local file, then
  2. load the new extension 'Autodesk.PDF', like this...
let viewer;

function initializeViewer( pdf ) {
   var options = {
        env: "Local",
        useADP: false
   }
   Autodesk.Viewing.Initializer(options, () => {
      viewer = new Autodesk.Viewing.Private.GuiViewer3D(document.getElementById('forgeViewer'));
      viewer.setTheme("light-theme");
      viewer.start();
      if (!pdf) return;
      viewer.loadExtension('Autodesk.PDF').then( () => {
            viewer.loadModel( pdf , viewer);
            viewer.loadExtension("Autodesk.Viewing.MarkupsCore")
            viewer.loadExtension("Autodesk.Viewing.MarkupsGui")
      });
});

 

Going Offline:

Borrowing from Petr Broz's fantastic blog post on offline (Disconnected workflows), I kicked off my 'offline-worker.js' like this...

if ('serviceWorker' in navigator)
  navigator.serviceWorker.register('offline-worker.js');

 

Then in my offline-worker.js code, I need to make sure I add these extensions to my static-cache list...

 

    'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/PDF/PDF.min.js',
	'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/PDF/PDF.worker.min.js',
	'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/Markup/Markup.min.js',
	'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/Measure/Measure.min.js',
	'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/Hyperlink/Hyperlink.min.js',
	'https://developer.api.autodesk.com/modelderivative/v2/viewers/6.*/extensions/CompGeom/CompGeom.min.js',

I also add the three example PDF files I want to work offline...

	'/pdfs/qcad1.pdf',
	'/pdfs/qcad3.pdf',
	'/pdfs/wood.pdf',

And finally, I add my 'fetch()' interceptor and use a simple caching strategy.

async function fetchAsync(event) {
    const match = await caches.match(event.request.url, { ignoreSearch: true });
    if (!match) return fetch(event.request);
    if (STATIC_URLS.includes(event.request.url)) {
        caches.open(CACHE_NAME)
            .then((cache) => cache.add(event.request))
            .catch((err) => console.log('Cache not updated, but that\'s ok...', err));
    }
    return match;
}

  

Now, when you first load the page on your mobile phone or iPad for the first time, it will download everything it needs to make sure you can view the 3 pdf's when you go offline, as well as markup and measure... all at super fast rendering speeds.

 

Note: Currently the markup is not saved or restored from IndexDB.  I'll leave that as an exercise to the reader.

Also, feel free to add your own PDF files to try out.

GITHUB: SOURCE-CODE 

LIVE-DEMO

Twitter: @micbeale

 

Related Article