[SOLVED] Viewing a .PDF file

I have a .PDF file of 85 pages that I would like to make available for viewing in my application.

I have considered converting that file to PNG pictures, that I could display inside a scrollView component.

The problem is that to have a correct visual quality, the converted .PNG files makes 8MB, while the original .PDF is about 3MB :scream:
(I used Image Magick, to convert the .PDF file into .PNG ones, with the command line convert -density 144 manual.pdf manual.png)
(I tried with .JPG images first, but the result is even worse)

Is there any way to view a .PDF file directly from within a Cocos Creator application?

Any suggestion would be appreciated.
Thanks


Daniel

or perhaps you can use https://mozilla.github.io/pdf.js/ on some sort of webview or something??

I also think you should try a solution involving webview.

Thanks for the suggestion, I will check pdf.js and see how I can integrate it into my application.

webview doesn’t seem to be supported (yet) with Cocos Creator: any idea/example of what I can do instead?


Daniel

Add an empty node to the scene and add the webview to that node manually?

Thanks for the suggestion, Boby, but I can’t do something like new ccui.WebView("my_pdf_file"); as there is no WebView in Cocos Creator API :cry:
(EDIT: I just checked cocos2d-js.js file, and its confirmed, there is no WebView support in it)

I’m not a JavaScript expert, so if someone could explain me (an example would be wonderfull :wink: ) how to ‘embed’ a .PDF file into my Cocos Creator application, using previously mentioned pdf.js or anything else, that would be very cool!!


Daniel

Hm, didn’t know that, strange. Wasn’t Creator supposed to integrate the whole cocos2d-x library?

Edit: Indeed, I can’t find WebView in the API Reference either. Wondering what other cocos2d-x features are still missing from Creator.

I’m still having big troubles to embed a PDF file into my Cocos Creator application… :frowning:

If someone succeeded doing it, or have any idea on how to make it working, I would love to see some example code!


Daniel

Ok, I have almost solved my troubles, here is how:

I first tried to work with pdf.js and pdf.worker.js, which are the files we should use in normal cases, but there was too much problems:

I first had to work around Cocos Creator complaining about node-ensure.
Then there was an other problem involving PDFJS.workerSrc which I was able to initialise correctly when using the version played directly from Cocos Creator, but not with the version built :frowning:

Solution for those troubles: just use file pdf.combined.js (which contain pdf.js and pdf.worker.js combined into one single file) which can be found on that repository: https://github.com/mozilla/pdfjs-dist

With this file, Cocos Creator does not ‘complain’ anymore, no need to change the source code to work around node-ensure problem, no need to setup PDFJS.workerSrc, it just work OOTB!

Here is an example code:

var url = cc.url.raw('resources/myfile.pdf');
PDFJS.getDocument(url).then(function(pdfDocument) {
    console.log('Document ' + url + ' contain ' + pdfDocument.numPages + ' page(s)');
}, function(failureReason) {
    console.log('An error occured with PDF file ' + url + ' : ' + failureReason);
});

Now, I just need to unserstand rendering context stuff…I’ll create a new thread for that and will update this one once the solution will be 100% working fine.


Daniel

Thanks to the help of Huabin (aka @pandamicro), I was able to solve my context rendering problem.

Here is an example code displaying the first page of a PDF file.

First, you need to add to Cocos Creator the script file pdf.combined.js (which contain pdf.js and pdf.worker.js combined into one single file) which can be found on that repository: https://github.com/mozilla/pdfjs-dist

(you need to create a ‘resources’ directory into assets and put the PDF file in it)
(pdfSprite is a cc.Sprite already added to current scene canvas)

cc.Class({
    extends: cc.Component,

    properties: {
        // Sprite that will contain a rendered PDF page
        pdfSprite: {
            default: null,
            type: cc.Sprite
        },
    (…)
    },
    //-------------------------------
    onLoad: function () {
        var self = this;

        self.displayPDFPage('resources/document.pdf', 1);
    },

    //-------------------------------
    displayPDFPage: function(filename, pageNumber) {
        var self = this;

        // Build an URL with specified document file
        var url = cc.url.raw(filename);

        // Get and open the PDF document
        PDFJS.getDocument(url).then(function(pdfDocument) {
            console.log('Document ' + url + ' contain ' + pdfDocument.numPages + ' page(s)');

            // Render the requested page
            pdfDocument.getPage(pageNumber).then(function(page) {

                // Get PDF page width & height
                var scale = 1;
                var viewport = page.getViewport(scale);

                // Create a canvas and get the corresponding 2d drawing context, in which the PDF page will be rendered
                var PDFcanvas = document.createElement('Canvas');
                PDFcanvas.width = viewport.width;
                PDFcanvas.height = viewport.height;
                var PDFcontext = PDFcanvas.getContext('2d');

                var renderContext = {
                    canvasContext: PDFcontext,
                    viewport: viewport
                };
                // Render the PDF page with this context 
                page.render(renderContext).then(function() {

                    // Build a spriteFrame and use that context as texture source
                    var texture2d = new cc.Texture2D();
                    texture2d.initWithElement(PDFcanvas);
                    texture2d.handleLoadedTexture();

                    self.pdfSprite.spriteFrame = new cc.SpriteFrame(texture2d, cc.rect(0, 0, PDFcanvas.width, PDFcanvas.height));

                    // Adjust height of the sprite according to document aspect ratio
                    var ratio = PDFcanvas.height / PDFcanvas.width;
                    self.pdfSprite.node.height = self.pdfSprite.node.width * ratio;

                }, function(failureReason) {
                    console.log('**!!** An error occured when rendering page ' + pageNumber + ' : ' + failureReason);
                });

            }, function(failureReason) {
                console.log('**!!** An error occured when accessing page ' + pageNumber + ' : ' + failureReason);
            });

        }, function(failureReason) {
            console.log('**!!** An error occured with PDF file ' + url + ' : ' + failureReason);
        });
    },
    (...)


Daniel

3 Likes

how did you manage to include the pdfjs library and how did you use pdf.combined.js, I did not understand how you did …

1 Like

How do you manage to make it work in the built code? When you build it, the resources has bundled and the url resulted by url.raw does not work anymore for me.

How can I get a URL for a built resource?