Pdf.js: PDF are displayed mirror-reflected and vertical diverted, when using pdf.js in AngularJS application

Created on 2 Oct 2013  路  11Comments  路  Source: mozilla/pdf.js

Hi,

I've got similar issue corresponding to previously reported #3665, but it occurs in quite different enviroment, so I've created separate issue for this.

Details:
I use pdf.js in some application. HTML5 views are generated by Java-based backend (JSP, Spring), where I've integrated AngularJS to manipulate client-side code directly in web browser.

I've got an Angular service, which is simple wrapper for pdf.js basic functionality:

application.service("PdfjsService", [ function() {
    // reference to service for callbacks
    var __service = this;

    this.url = "";

    this.canvasId = "";

    // initial values
    this.page = 1;
    this.scale = 1.0;

    this.init = function(canvasId, page, scale) {
        this.canvasId = canvasId;
        if (scale) {
            this.scale = scale;
        }

        if (page) {
            this.page = page;
        }
    };

    this.render = function(url) {
        if (PDFJS) {
            PDFJS.getDocument(url).then(function(pdf) {
                pdf.getPage(__service.page).then(function(page) {
                var scale = __service.scale;
                var viewport = page.getViewport(scale);

                var canvas = document.getElementById(__service.canvasId);
                var context = canvas.getContext('2d');
                canvas.height = viewport.height;
                canvas.width = viewport.width;

                var renderContext = {
                  canvasContext: context,
                  viewport: viewport
                };
                page.render(renderContext);
              });
            });

        }

    };
}]);

I can call this service in two different ways:

  • only in controller, like this:
// other code in Angular controller

PdfjsService.init('the-canvas', 1, 1);
PdfjsService.render('${contextPath}/resources/img/somefile.pdf');

// other code in Angular controller

or

  • directly in JSP HTML5 code, after passing reference to PdfjsService as $scope var:

controller:

// other code in Angular controller


            PdfjsService.init('the-canvas', 1, 1);
            $scope.pdfservice = PdfjsService;

// other code in Angular controller

and view:

<!-- other HTML -->

 <div class="span4">
    <canvas id="the-canvas" style="border:1px solid black; width:350px;"/>
  </div>
  {{pdfservice.render('${contextPath}/resources/img/somefile.pdf')}}

<!-- other HTML -->


${contextPath} is Spring variable, which has no impact for whole situation (it's only a part of path to pdf file).

Pdf file is visible in both cases, only in the second one is diverted vertical and mirrored :/

I can't attach this specific pdf file, because it's confidential (it's a part of commercial project and only for internal use)

1-other

Most helpful comment

Looks like the issue was resolve. Closing.

The "mirrored" canvas display happens:
1) when multiple render tasks a painting to the same canvas;
2) or, canvas was reset (by changing width or height) during render task.

To avoid this, don't (re)use the canvas until the page rendering is finished or canceled.

All 11 comments

With only code snippets, it will be difficult (or impossible) for anyone to help. Please see: https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#wiki-custom.

Ok, sorry.
I had to find another pdf file and I recreated this issue with this one:

http://www.zotero.org/static/download/zotero_mini_guide.pdf

Same situation as described above, when using directly in view, pages are diverted and mirrored.

pdf above works for me. please provide more information

Ok, I've created a simple working example with all dependences (Angular.js, pdf.js and sample pdf file). The problem occurs as described in this issue. Checked in Chrome 30.0.1599.66 (OSX Mountain Lion 10.8.5)

https://github.com/bl4de/pdfjs_angularjs

If anyone could help with this issue, thanks a lot.

@bl4de I tried cloning your example and fiddled a bit with it. In Firefox, the results are varying a lot, but the rightmost test fails almost all the time. Sometimes, the images are indeed mirror-reflected, but most of the time they're not even shown at all and sometimes the image is shown correctly. I do not know enough about Angular.js to tell you why this is happening, but this is most likely an Angular.js related implementation problem. Not sure as to why though. Maybe someone else can jump in and help out here?

@timvandermeij Thank You for Your response. I think main problem is with Angular rather than pdf.js itself. For now we (I mean me and my colleagues in team) use rendering method outside Angular's view :) Works fine for now, but the problem is still very interesting and we still try to find the cause anyway.

Looks like the issue was resolve. Closing.

The "mirrored" canvas display happens:
1) when multiple render tasks a painting to the same canvas;
2) or, canvas was reset (by changing width or height) during render task.

To avoid this, don't (re)use the canvas until the page rendering is finished or canceled.

@yurydelendik can you please tell me how can avoid the reuse of canvas until the page rendering is finished or canceled? We are facing this issue a lot in our application. The version that we are using is 1.6.217

@varun-bansal the render() method's promise is not resolve until rendering finished/cancel. So either wait on this promise or just use different canvas. The example for the former can be found at https://github.com/mozilla/pdf.js/blob/master/examples/learning/prevnext.html . You can also just use PDFPageView class, which implements that.

@yurydelendik Thanks for the help :+1:

@yurydelendik I am facing an identical issue myself. I'm working on an AngularJS application where one of the core requirements is to view and sign off PDFs.

At the moment I've got a working PDF that I'm using as a placeholder which I reference by its path. It displays fine in any traditional PDF-reader, but when I attempt to reference it in Angular the pdf comes out distorted.

I've used an identical implementation as the onPrevNext that you referred Varun to:

`(function () {

"use strict";

angular.module('kioskApp')
    .controller('pdfpageController', pdfpageController);

function pdfpageController($http, $scope, $window, $mdDialog, $sce, user, apiController) {
    let vm = this;
    vm.isBusy = true;
    let fileURL;
    $scope.content;
    $scope.boundingBox = {
        width: 700,
        height: 300
    };

    let pdfDoc = null,
        pageNum = 1,
        pageRendering = false,
        pageNumPending = null,
        scale = 1,
        canvas = document.getElementById('test-canvas'),
        ctx = canvas.getContext('2d');

    function renderPage(num) {

        pageRendering = true;

        pdfDoc.getPage(num).then(function (page) {
            let viewport = page.getViewport(scale);
            canvas.height = viewport.height;
            canvas.width = viewport.width;

            let renderContext = {
                canvasContext: ctx,
                viewport: viewport
            };

            let renderTask = page.render(renderContext);

            renderTask.promise.then(function () {
                pageRendering = false;

                if (pageNumPending !== null) {
                    renderPage(pageNumPending);
                    pageNumPending = null;
                }
            });
        });
        document.getElementById('page_num').textContent = pageNum;
    }

    function queueRenderPage(num) {
        if (pageRendering) {
            pageNumPending = num;
        } else {
            renderPage(num);
        }
    }

    function onPrevPage() {
        if (pageNum <= 1) {
            return;
        }
        pageNum--;
    }

    document.getElementById('prev').addEventListener('click', onPrevPage);

    function onNextPage() {
        if (pageNum >= pdfDoc.numPages) {
            return;
        }
        pageNum++;
        queueRenderPage(pageNum);
    }
    document.getElementById('next').addEventListener('click', onNextPage);




    $scope.goback = function () {
        $window.location.href = '#!/additional';
    } 

    vm.content = {
        "where": "WHERE UserID = 3333 AND WorksiteID = 3395",
        "strcon": "JaberoSiteManagement"
    };


    function queueRenderPage(num) {
        if (pageRendering) {
            pageNumPending = num;
        } else {
            renderPage(num);
        }
    }


    function setPdf(pdf) {
        PDFJS.getDocument(pdf).then(function (pdfDoc_) {
            pdfDoc = pdfDoc_;
            document.getElementById('page_count').textcontent = pdfDoc.numPages;

            renderPage(pageNum);

        });
    }
    $http.post("http://somedata.com/api/test_pdf_table/get/", JSON.stringify(vm.content))
        .then(function (response) {
            //success

            vm.data = response.data;
        },
        function (error) {

        })
        .finally(function () {
            setPdf(vm.data[0].Path);
        });


}

})();`

The code runs intended with no errors (but some small warnings regarding the arraybuffer:

The provided value 'moz-chunked-arraybuffer' is not a valid enum value of type XMLHttpRequestResponseType.

I'd love to hear your thoughts about this. You can find the example on our website

Was this page helpful?
0 / 5 - 0 ratings

Related issues

PeterNerlich picture PeterNerlich  路  3Comments

dmisdm picture dmisdm  路  3Comments

azetutu picture azetutu  路  4Comments

SehyunPark picture SehyunPark  路  3Comments

patelsumit5192 picture patelsumit5192  路  3Comments