PDF.js document is presented upside down randomly - javascript

I'm using PDF.js addon to show pdfs in my polymerjs app. From time to time pdf content is rendered upside down. Here is how I'm using PDF.js:
downloadPdf: function(item) {
var pdfJsInitParams = {
url: app.baseURL + item.report_pdf,
httpHeaders: app.user.token
};
PDFJS.getDocument(pdfJsInitParams).promise.then(function(pdf) {
function renderPage(pageNumber, eltId) {
if(pdf.numPages < pageNumber) {
return;
}
pdf.getPage(pageNumber).then(function(page) {
var scale = 1.3;
var viewport = page.getViewport(scale);
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById(eltId);
if(canvas) {
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
page.render(renderContext);
}
}).catch(function(err) {
showToastWithText(err, 'error');
});
}
renderPage(1, 'report_1');
renderPage(2, 'report_2');
});
}
Any ideas what may causing this issue?

(Looks like downloadPdf is called multiple times in short period of time)
The render() operation is asynchronous and you need to wait for its completion before you start a new rendering on the same canvas, see https://github.com/mozilla/pdf.js/blob/master/examples/learning/prevnext.html example. If you don't want to wait, create a new canvas.

Related

Rendering with PDF.js - misprinting issue

I am working on PDF.js and trying to render a pdf on a webpage. I am facing misprinting issue when displaying pdf. You can see that some text is not printed properly
Bad display
However, when I see the pdf in Acrobat, it is displayed perfectly.
Good Display
Note* - The Pdf contains only text, no images.
I'm using very basic code to display the pdf file
var url = './highlighter_updated.pdf';
// Loaded via <script> tag, create shortcut to access PDF.js exports.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
// Asynchronous download of PDF
var loadingTask = pdfjsLib.getDocument(url);
loadingTask.promise.then(function(pdf) {
console.log('PDF loaded');
// Fetch the first page
var pageNumber = 1;
pdf.getPage(pageNumber).then(function(page) {
console.log('Page loaded');
var scale = 1.0;
var viewport = page.getViewport({scale});
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('the-canvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: context,
viewport: viewport
};
var renderTask = page.render(renderContext);
renderTask.promise.then(function () {
console.log('Page rendered');
});
});
}, function (reason) {
// PDF loading error
console.error(reason);
});
Can anyone suggest what is wrong with this.
Thanks in advance.

How can I get the position of an HTML element when the browser window is resized?

I have a function that draw a CANVAS line and make its get the same coordinates of a <div> by using offsetLeft. The line searchs the same position of the <div> making its get glued on the <div> It is working good BUT ONLY when the page loads and the browser refreshs.
drawCanvas() {
const c = document.getElementById("canvas");
const lineH = c.getContext("2d");
c.width = window.innerWidth;
c.height = window.innerHeight;
const lineV = c.getContext("2d");
const positionCanvas = () => {
lineV.clearRect(0, 0, c.width, c.height);
const divPosition = document.querySelector('.myDiv').offsetLeft
lineV.fillStyle = "grey";
lineV.fillRect(divPosition , 0, 2, window.innerHeight);
lineV.fill();
}
positionCanvas()
window.onresize = () => {
lineV.height = window.innerHeight;
positionCanvas()
}
I would like to make it work good everytime even and especially when I'm handling the resizing of the window. How can I solve it?
Example:
The page is loaded:
OK!!! The canvas line is glued on <div>
While the user is manually resizing the window's browser:
NOT WORKING!!! The canvas search the <div> but not get glued on its,
there is a distance between both.
After the stop of the browser resizing:
NOT WORKING!!! the lline still separated from the <div>
Refresh the browser in a new position:
OK!!! canvas line is glued on <div>
I found the solution.
Just put the function drawCanvas() into the window.onresize rather the positionCanvas().
Just like that:
window.onresize = () => {
drawCanvas()
}

Firefox drawing blank Canvas when restoring from saved base64

I am working with a single canvas that allows the user to click on a window pane in a window image. The idea is to show where the user has clicked. The image will then be modified (by drawing a grill on the window) and then saved to in JPEG. I am saving the canvas image prior to the click function because I don't want the selection box to show in the final image. However, Firefox often displays a blank canvas when restoring the canvas where IE and Chrome do not. This works perfectly in Chrome and IE. Any suggestions? Does Firefox have a problem with toDataURL()? Maybe some async issue going on here? I am also aware that saving a canvas in this fashion is memory intensive and there may be a better way to do this but I'm working with what I have.
Code:
/**
* Restores canvas from drawingView.canvasRestorePoint if there are any restores saved
*/
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.src = drawingView.canvasRestorePoint.pop();
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
}
},
/**
* Pushes canvas into drawingView.canvasRestorePoint
*/
saveCanvas:function()
{
var canvas = document.getElementById("drawPop.canvasOne");
var urlData = canvas.toDataURL();
drawingView.canvasRestorePoint.push(urlData);
},
EXAMPLE OF USE:
readGrillInputs:function()
{
var glassNum = ir.get("drawPop.grillGlassNum").value;
var panelNum = ir.get("drawPop.grillPanelNum").value;
drawingView.restoreCanvas();
drawEngine.drawGrill(glassNum, panelNum,null);
drawingView.saveCanvas();
},
sortClick:function(event)
{
..... //Sorts where user has clicked and generates panel/glass num
.....
drawingView.showClick(panelNum, glassNum);
},
showClick:function(panelNum, glassNum)
{
var glass = item.panels[panelNum].glasses[glassNum];
var c = drawEngine.context;
drawingView.restoreCanvas();
drawingView.saveCanvas();
c.strokeStyle = "red";
c.strokeRect(glass.x, glass.y, glass.w, glass.h);
},
By just looking at the code setting the img.src is an async action to retrieve the image, so when you try to draw it 2 lines later to the canvas, it probably hasn't been loaded yet (having it in cache will make it return fast enough that it might work).
You should instead use an img.onload function to draw the image when it has loaded.
restoreCanvas:function()
{
var inverseScale = (1/drawingView.scaleFactor);
var canvas = document.getElementById("drawPop.canvasOne");
var c = canvas.getContext("2d");
if (drawingView.canvasRestorePoint[0]!=null)
{
c.clearRect(0,0,canvas.width,canvas.height);
var img = new Image();
img.onload = function() {
c.scale(inverseScale,inverseScale);
c.drawImage(img, 0, 0);
c.scale(drawingView.scaleFactor, drawingView.scaleFactor);
};
img.src = drawingView.canvasRestorePoint.pop();
}
},

PDF Js does not work in meteor

I am using Mozilla pdf js in meteor. The package I am using is from "https://atmospherejs.com/pascoual/pdfjs"
I am doing almost everything that they have stated in their example, but my pdf file is delivered as a image file. It is not getting displayed as shown in their example "https://mozilla.github.io/pdf.js/web/viewer.html".
Please let me know what have I done wrong. My code is as follows:
<template name="displayResume">
<canvas id="pdfcanvas"></canvas>
</template>
Template.displayResume.rendered = function(){
PDFJS.workerSrc = '/packages/pascoual_pdfjs/build/pdf.worker.js';
console.log(PDFJS)
//PDFJS.workerSrc = '/.meteor/local/build/programs/web.browser/packages/pascoual_pdfjs/build/pdf.worker.js';
var url = '/Lez6dci9xoaiyWuzR.pdf';
PDFJS.getDocument(url).then(function getPdfHelloWorld(pdf) {
// Fetch the first page
pdf.getPage(1).then(function getPageHelloWorld(page) {
var scale = 1;
var viewport = page.getViewport(scale);
// Prepare canvas using PDF page dimensions
var canvas = document.getElementById('pdfcanvas');
var context = canvas.getContext('2d');
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
page.render({canvasContext: context, viewport: viewport}).promise.then(function () {
console.log('rendered');
});
});
});
}
I am just trying to display resume from my public folder as of now. Later, I will have to display file from amazon aws.
Thanks in advance
they had a pageviewer example here:
https://github.com/mozilla/pdf.js/blob/master/examples/components/pageviewer.js
I think the line you are looking for is:
textLayerFactory: new PDFJS.DefaultTextLayerFactory(),

How to destroy / reload the canvas in html 5?

I am working on an ebook application, I draw each page on canvas using PDF.js , the problem is , when I click on the button and turn to other page, I tried simply render on the same canvas again , but the canvas seems move to a wrong location or wrong size .
function renderPage(url) {
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
//clearCanvasGrid('canvas');
PDFJS.getDocument(url).then(function (pdf) {
// Using promise to fetch the page
pdf.getPage(1).then(function(page) {
var viewport = page.getViewport(5); //scale 5
canvas.height = viewport.height;
canvas.width = viewport.width;
// Render PDF page into canvas context
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext).then(function() {
initialZoomPage(viewport.height,viewport.width);
});
});
});
}
So, are there any necessary step I need to do before redraw the page? Also , how can I destroy it if I would like to close the page? Thanks
Update:
function clearCanvasGrid(canvasID){
canvas = document.getElementById(canvasID); //because we are looping //each location has its own canvas ID
context = canvas.getContext('2d');
//context.beginPath();
// Store the current transformation matrix
context.save();
// Use the identity matrix while clearing the canvas
context.setTransform(1, 0, 0, 1, 0, 0);
context.clearRect(0, 0, canvas.width, canvas.height);
// Restore the transform
context.restore(); //CLEARS THE SPECIFIC CANVAS COMPLETELY FOR NEW DRAWING
}
I found a function to clear the canvas but it has .save , .setTransform and .restore besides clearRect, are they necessary? thanks
One way is to clear out the canvas using context.clearRect(0,0, width, height) (Reference).
Alternatively, you can append a new canvas element (and possibly remove the old one, depending on whether you will want to display it again) each time you want a new page. Something like this should do it:
var oldcanv = document.getElementById('canvas');
document.removeChild(oldcanv)
var canv = document.createElement('canvas');
canv.id = 'canvas';
document.body.appendChild(canv);
Just note that if you plan to keep more than one, each one must have a unique id instead of just id="canvas" (perhaps based on the page number - something like canvas-1).
Answer to updated question:
The save, setTransform, and restore are only necessary if you are doing (or somehow allowing users to do) transformation. I don't know if the PDF.js library does any transformation behind the scenes, so it may be best to leave it there.
try using clearRect(), like:
canvas = document.getElementById('canvas');
ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
In Lightning Aura components, a different approach is required:
The chart object, once created, is stored in an attribute.
<aura:attribute name="chartObject" type="Object"/>
<canvas id="chartId" aura:id="chartCanvas" </canvas>
let theChart = component.get("v.chartObject");
if (theChart != undefined) {
//alternative
//let chartStatus = Chart.getChart("chartId");
//if (chartStatus != undefined) {
//update data if necessary
//theChart.data.datasets[0].data[i] = etc
theChart.update();
}
else{
var ctx = component.find("chartCanvas").getElement();
var chart = new Chart(ctx, {
type: 'line',
data: myData,
options: {
tension: 0.25,
responsive: false,
maintainAspectRatio :false,
fill: true,
}
});
component.set("v.chartObject", chart);
}//endif chart exists

Categories

Resources