I'm trying to update my pdf preview when I resize my window.
For now my canvas's size is changing, but the pdf preview is keeping the same size.
How can't find a way to do this.
var myState = {
pdf: null,
currentPage: 1,
zoom: 1
}
function domLoad() {
myState.pdf.getPage(myState.currentPage).then((page) => {
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var viewport = page.getViewport(myState.zoom);
var heightRatio = 842 / 595;
canvas.width = ((((595/941.39)*100)*window.innerWidth)/100);
canvas.height = ((((595/941.39)*100)*window.innerWidth)/100) * heightRatio;
page.render({
canvasContext: ctx,
viewport: viewport
});
updateCanvas(canvas);
});
}
document.addEventListener('DOMContentLoaded', function(event) {
pdfjsLib.getDocument('https://www.ecam.fr/wp-content/uploads/sites/3/2016/06/Exemple-fichier-PDF-1.pdf').then((pdf) => {
myState.pdf = pdf;
render();
});
function render() {
domLoad();
}
})
addEventListener("resize", (event) => {
domLoad();
});
function updateCanvas(canvas) {
var canvasParent = document.getElementById("pdf_container");
var previousCanvas = canvasParent.querySelector('canvas');
if(previousCanvas !== null) {
canvasParent.removeChild(previousCanvas);
}
canvasParent.appendChild(canvas);
}
body { width: 100%; height: 100%; }
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.0.943/pdf.min.js"></script>
</head>
<body>
<a id="pdf_container" class="pdf_container" href="https://www.ecam.fr/wp-content/uploads/sites/3/2016/06/Exemple-fichier-PDF-1.pdf">
</a>
</div>
</body>
I tried to remove the canvas when I'm resizing the window, and add it back with another size for now.
The canvas's size is changing but the pdf preview inside won't fit it.
Reading : This solution
I managed to fix this, the viewport was the answer. The problem was the name of getViewport (it can also be a setter) :
var viewport = page.getViewport(canvas.width / page.getViewport(myState.zoom).width);
var myState = {
pdf: null,
currentPage: 1,
zoom: 1
}
function domLoad() {
myState.pdf.getPage(myState.currentPage).then((page) => {
var canvas = document.createElement('canvas');
canvas.id = 'pdf_renderer';
var ctx = canvas.getContext('2d');
console.log(page);
var heightRatio = 842 / 595;
canvas.width = ((((595/941.39)*100)*window.innerWidth)/100);
canvas.height = ((((595/941.39)*100)*window.innerWidth)/100) * heightRatio;
var viewport = page.getViewport(canvas.width / page.getViewport(myState.zoom).width);
page.render({
canvasContext: ctx,
viewport: viewport
});
updateCanvas(canvas);
});
}
document.addEventListener('DOMContentLoaded', function(event) {
pdfjsLib.getDocument('../documents/cv.pdf').then((pdf) => {
myState.pdf = pdf;
render();
});
function render() {
domLoad();
}
})
addEventListener("resize", (event) => {
domLoad();
});
function updateCanvas(canvas) {
var canvasParent = document.getElementById("pdf_container");
var previousCanvas = canvasParent.querySelector('canvas');
if(previousCanvas !== null) {
canvasParent.removeChild(previousCanvas);
}
canvasParent.appendChild(canvas);
}
Related
I am trying to create a logo and try to add a logo in the middle of the qr code and i am able to generate the qr code but unable to get the qr code with logo on the middle i have tried this code but unable to get the result getting this error
Error: You need to specify a canvas element
and i am using this library https://github.com/soldair/node-qrcode
and here is the tried code
const QRCode = require("qrcode");
const getQRcodeImage = async () => {
try {
let canvas = await QRCode.toCanvas(`my sample text`);
//adding a log at center
const imgDim = { width: 30, height: 30 }; //logo dimention
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = "./Capture.png";
imageObj.onload = function () {
context.drawImage(
imageObj,
canvas.width / 2 - imgDim.width / 2,
canvas.height / 2 - imgDim.height / 2,
imgDim.width,
imgDim.height
);
};
return canvas;
} catch (e) {
console.error(e);
return "";
}
};
getQRcodeImage();
const QRCode = require("qrcode");
const { createCanvas, loadImage } = require("canvas");
async function create(dataForQRcode, center_image, width, cwidth) {
const canvas = createCanvas(width, width);
QRCode.toCanvas(
canvas,
dataForQRcode,
{
errorCorrectionLevel: "H",
margin: 1,
color: {
dark: "#000000",
light: "#ffffff",
},
}
);
const ctx = canvas.getContext("2d");
const img = await loadImage(center_image);
const center = (width - cwidth) / 2;
ctx.drawImage(img, center, center, cwidth, cwidth);
return canvas.toDataURL("image/png");
}
async function main() {
const qrCode = await create(
"http://shauryamuttreja.com/qr/",
"data:image/png;base64,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",
150,
50
);
console.log(qrCode);
}
main();
I want to show PDF file with multiple pages in canvas html tag like this:
<canvas class="pdfViewer hidden" style="border: solid 1px black;width: 100%;"></canvas>
The library which I'm using is jsPDF. But, its showing single page preview only using this code.
var pdfjsLib = window['pdfjs-dist/build/pdf'];
// The workerSrc property shall be specified.
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';
$("input[type='file']").on("change", function (e) {
$("button[name='Preview']").removeClass("hidden");
var file = e.target.files[0]
if (file.type == "application/pdf") {
var fileReader = new FileReader();
fileReader.onload = function () {
var pdfData = new Uint8Array(this.result);
// Using DocumentInitParameters object to load binary data.
var loadingTask = pdfjsLib.getDocument({ data: pdfData });
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.5;
var viewport = page.getViewport({ scale: scale });
// Prepare canvas using PDF page dimensions
var canvas = $(".pdfViewer")[0];
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);
});
};
fileReader.readAsArrayBuffer(file);
}
});
I want it in multiple pages like if PDF is of 5-10 pages then should show that many number of pages.
Add a div to append <canvas> to render multiple pages.
I modify your code and it works, like this:
HTML
<div id='pdf-viewer'></div>
Javascript
var thePdf = null;
var scale = 1.5;
function renderPage(pageNumber, canvas) {
thePdf.getPage(pageNumber).then(function (page) {
viewport = page.getViewport({ scale: scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
page.render({ canvasContext: canvas.getContext('2d'), viewport: viewport });
})
};
var pdfjsLib = window['pdfjs-dist/build/pdf'];
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://mozilla.github.io/pdf.js/build/pdf.worker.js';
$("input[type='file']").on("change", function (e) {
$("button[name='Preview']").removeClass("hidden");
var file = e.target.files[0]
if (file.type == "application/pdf") {
var fileReader = new FileReader();
fileReader.onload = function () {
var pdfData = new Uint8Array(this.result);
var loadingTask = pdfjsLib.getDocument({ data: pdfData });
loadingTask.promise.then(function (pdf) {
thePdf = pdf;
viewer = document.getElementById('pdf-viewer');
for(page = 1; page <= pdf.numPages; page++) {
canvas = document.createElement("canvas");
canvas.className = 'pdf-page-canvas';
viewer.appendChild(canvas);
renderPage(page, canvas);
}
}, function (reason) {
// PDF loading error
console.error(reason);
});
};
fileReader.readAsArrayBuffer(file);
}
});
Im trying to develop a frontend code that asks the user to provide a pdf and then internally (in the users browser) produces an array of png's (via data to url) where each entry in the array corresponds to a page in the pdf:
dat[0] = png of page 1
dat[1] = png of page 2
...
When I test the below code the pages are somehow rendered on top of eachother and rotated.
<script src="http://cdnjs.cloudflare.com/ajax/libs/processing.js/1.4.1/processing-api.min.js"></script><html>
<!--
Created using jsbin.com
Source can be edited via http://jsbin.com/pdfjs-helloworld-v2/8598/edit
-->
<body>
<canvas id="the-canvas" style="border:1px solid black"></canvas>
<input id='pdf' type='file'/>
<!-- Use latest PDF.js build from Github -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="pdf.js"></script>
<script src="pdf.worker.js"></script>
<script type="text/javascript">
//
// Asynchronous download PDF as an ArrayBuffer
//
dat = [];
var pdf = document.getElementById('pdf');
pdf.onchange = function(ev) {
if (file = document.getElementById('pdf').files[0]) {
fileReader = new FileReader();
fileReader.onload = function(ev) {
//console.log(ev);
PDFJS.getDocument(fileReader.result).then(function getPdfHelloWorld(pdf) {
//
// Fetch the first page
//
number_of_pages = pdf.numPages;
for(i = 1; i < number_of_pages+1; ++i) {
pdf.getPage(i).then(function getPageHelloWorld(page) {
var scale = 1;
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};
page.render(renderContext).then(function() {
dat.push(canvas.toDataURL('image/png'));
});
});
}
//console.log(pdf.numPages);
//console.log(pdf)
}, function(error){
console.log(error);
});
};
fileReader.readAsArrayBuffer(file);
}
}
</script>
<style id="jsbin-css">
</style>
<script>
</script>
</body>
</html>
Im only interested in the array dat. When I render the images in the array I see that
dat[0] = png of page 1 (correct)
dat[1] = png of page 1 and png page 2 rotated 180 on top of each other
...
How do I ensure a correct rendering of single pages in each entry of the array?
Try rendering the pages on a different canvas. You can create a canvas and append it to the container using
var canvasdiv = document.getElementById('canvas');
var canvas = document.createElement('canvas');
canvasdiv.appendChild(canvas);
var url = 'https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf';
var PDFJS = window['pdfjs-dist/build/pdf'];
PDFJS.GlobalWorkerOptions.workerSrc = '//mozilla.github.io/pdf.js/build/pdf.worker.js';
var loadingTask = PDFJS.getDocument(url);
loadingTask.promise.then(function(pdf) {
var canvasdiv = document.getElementById('canvas');
var totalPages = pdf.numPages
var data = [];
for (let pageNumber = 1; pageNumber <= totalPages; pageNumber++) {
pdf.getPage(pageNumber).then(function(page) {
var scale = 1.5;
var viewport = page.getViewport({ scale: scale });
var canvas = document.createElement('canvas');
canvasdiv.appendChild(canvas);
// Prepare canvas using PDF page dimensions
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() {
data.push(canvas.toDataURL('image/png'))
console.log(data.length + ' page(s) loaded in data')
});
});
}
}, function(reason) {
// PDF loading error
console.error(reason);
});
canvas {
border: 1px solid black;
margin: 5px;
width: 25%;
}
<script src="//mozilla.github.io/pdf.js/build/pdf.js"></script>
<div id="canvas"></div>
For those who came here from google for an Angular solution here is an implementation, rendering each page on a different canvas.
pdf-viewer.component.html
<div *ngFor="let page of pages>
<canvas #canvas hidden ></canvas>
<img [src]="page">
</div>
pdf-viewer.component.ts
import * as pdfjsLib from 'pdfjs-dist';
pdfjsLib.GlobalWorkerOptions.workerSrc = 'pdf.worker.js';
#Component({
selector: 'app-pdf-viewer',
templateUrl: './pdf-viewer.component.html',
styleUrls: ['./pdf-viewer.component.scss'],
})
export class PdfViewerComponent implements OnInit {
constructor() { }
#ViewChildren('canvas') canvas: QueryList<ElementRef<HTMLCanvasElement>>;
#Input() pdfBase64: string;
pages: string[] = [];
ngOnInit(): void {
this.setPages();
}
async setPages(): Promise<void> {
const pdfDoc = await pdfjsLib.getDocument({ url: this.pdfBase64 }).promise;
const totalPages = pdfDoc.numPages;
this.pages = new Array(totalPages);
for (let i = 0; i < totalPages; i++) {
pdfDoc.getPage(i + 1).then((page) => {
const canvas = this.canvas.toArray()[page.pageIndex].nativeElement;
this.renderPdfPageToCanvas(page, canvas).then(() => {
this.pages[page.pageIndex] = canvas.toDataURL('image/png');
});
});
}
}
renderPdfPageToCanvas(page: pdfjsLib.PDFPageProxy, canvas: HTMLCanvasElement): pdfjsLib.PDFPromise<pdfjsLib.PDFPageProxy> {
const viewport = page.getViewport({ scale: 1.0 });
const height = viewport.height;
const width = viewport.width;
canvas.height = height;
canvas.width = width;
const renderContext = {
canvasContext: canvas.getContext('2d'),
viewport: viewport
};
return page.render(renderContext).promise;
}
}
package.json
{
...
"dependencies": {
...
"#angular/core": "^9.1.11",
"pdfjs-dist": "2.3.200"
},
"devDependencies": {
...
"#types/pdfjs-dist": "2.1.3"
}
}
I would like to generate a thumbnail from a pdf file using PDF.js, but it isn't like anothers js that have just one file and all needed to include the js in your project is to write:
<script src="any.js"></script>
How can I use PDF.js in my project? I'm using PHP in backend.
Based on helloworld example:
function makeThumb(page) {
// draw page to fit into 96x96 canvas
var vp = page.getViewport(1);
var canvas = document.createElement("canvas");
canvas.width = canvas.height = 96;
var scale = Math.min(canvas.width / vp.width, canvas.height / vp.height);
return page.render({canvasContext: canvas.getContext("2d"), viewport: page.getViewport(scale)}).promise.then(function () {
return canvas;
});
}
pdfjsLib.getDocument("https://raw.githubusercontent.com/mozilla/pdf.js/ba2edeae/web/compressed.tracemonkey-pldi-09.pdf").promise.then(function (doc) {
var pages = []; while (pages.length < doc.numPages) pages.push(pages.length + 1);
return Promise.all(pages.map(function (num) {
// create a div for each page and build a small canvas for it
var div = document.createElement("div");
document.body.appendChild(div);
return doc.getPage(num).then(makeThumb)
.then(function (canvas) {
div.appendChild(canvas);
});
}));
}).catch(console.error);
<script src="//npmcdn.com/pdfjs-dist/build/pdf.js"></script>
I figured it out, the scale is not a parameter. The parameters are an object with field of scale that needed to be set.
function makeThumb(page) {
// draw page to fit into 96x96 canvas
var vp = page.getViewport({ scale: 1, });
var canvas = document.createElement("canvas");
var scalesize = 1;
canvas.width = vp.width * scalesize;
canvas.height = vp.height * scalesize;
var scale = Math.min(canvas.width / vp.width, canvas.height / vp.height);
console.log(vp.width, vp.height, scale);
return page.render({ canvasContext: canvas.getContext("2d"), viewport: page.getViewport({ scale: scale }) }).promise.then(function () {
return canvas;
});
}
I tried rendering PDF document using pdf.js library. I know only basics in javascript and I am new to promises, so at first I followed advice on this page: Render .pdf to single Canvas using pdf.js and ImageData (2. answer). But as a result, I rendered my document with all pages blank. All pictures and colors are fine, but not even a line of text. I also tried some other tutorials, but either I get the same result, or the document is completely missing.
Right now, my code looks like this: (It's almost identical to the tutorial)
function loadPDFJS(pid, pageUrl){
PDFJS.disableWorker = true;
PDFJS.workerSrc = 'pdfjs/build/pdf.worker.js';
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var pages = [];
var currentPage = 1;
var url = '/search/nimg/IMG_FULL/' + pid + '#page=1';
PDFJS.getDocument(url).then(function (pdf) {
if(currentPage <= pdf.numPages) getPage();
function getPage() {
pdf.getPage(currentPage).then(function(page){
var scale = 1.5;
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
page.render(renderContext).then(function() {
pages.push(canvas.toDataURL());
if(currentPage < pdf.numPages) {
currentPage++;
getPage();
} else {
done();
}
});
});
}
});
function done() {
for(var i = 0; i < pages.length; i++){
drawPage(i, addPage);
}
}
function addPage(img){
document.body.appendChild(img);
}
function drawPage(index, callback){
var img = new Image;
img.onload = function() {
ctx.drawImage(this, 0, 0, ctx.canvas.width, ctx.canvas.height);
callback(this);
}
img.src = pages[index];
}
}
K so I just looked at my code again and I started all over. I made it simpler and I finally got it to work. Now it looks like this:
var canvasContainer = document.getElementById('pdfImageImg');
function loadPDFJS(pid, pageUrl){
PDFJS.workerSrc = 'pdfjs/build/pdf.worker.js';
var currentPage = 1;
var pages = [];
var url = '/search/nimg/IMG_FULL/' + pid + '#page=1';
PDFJS.getDocument(url).then(function(pdf) {
pdf.getPage(currentPage).then(renderPage);
function renderPage(page) {
var height = 700;
var viewport = page.getViewport(1);
var scale = height / viewport.height;
var scaledViewport = page.getViewport(scale);
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.height = scaledViewport.height;
canvas.width = scaledViewport.width;
var renderContext = {
canvasContext: context,
viewport: scaledViewport
};
page.render(renderContext).then(function () {
if(currentPage < pdf.numPages) {
pages[currentPage] = canvas;
currentPage++;
pdf.getPage(currentPage).then(renderPage);
} else {
for (var i = 1; i < pages.length; i++) {
document.getElementById('pdfImageImg').appendChild(pages[i]);
}
}
});
}
});
}
Thank you #user3913960, your concept worked for me. I found some issues in your code which I fixed. Here is the code:
function loadPDFJS(pageUrl) {
PDFJS.workerSrc = 'resources/js/pdfjs/pdf.worker.js';
var currentPage = 1;
var pages = [];
var globalPdf = null;
var container = document.getElementById('pdf-container');
function renderPage(page) {
//
// Prepare canvas using PDF page dimensions
//
var canvas = document.createElement('canvas');
// Link: http://stackoverflow.com/a/13039183/1577396
// Canvas width should be set to the window's width for appropriate
// scaling factor of the document with respect to the canvas width
var viewport = page.getViewport(window.screen.width / page.getViewport(1.0).width);
// append the created canvas to the container
container.appendChild(canvas);
// Get context of 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
};
page.render(renderContext).then(function () {
if (currentPage < globalPdf.numPages) {
pages[currentPage] = canvas;
currentPage++;
globalPdf.getPage(currentPage).then(renderPage);
} else {
// Callback function here, which will trigger when all pages are loaded
}
});
}
PDFJS.getDocument(pageUrl).then(function (pdf) {
if(!globalPdf){
globalPdf = pdf;
}
pdf.getPage(currentPage).then(renderPage);
});
}
loadPDFJS("somepdffilenamehere.pdf");
The pdfjs-dist library contains parts for building PDF viewer. You can use PDFPageView to render all pages. Based on https://github.com/mozilla/pdf.js/blob/master/examples/components/pageviewer.html :
var url = "https://cdn.mozilla.net/pdfjs/tracemonkey.pdf";
var container = document.getElementById('container');
// Load document
PDFJS.getDocument(url).then(function (doc) {
var promise = Promise.resolve();
for (var i = 0; i < doc.numPages; i++) {
// One-by-one load pages
promise = promise.then(function (id) {
return doc.getPage(id + 1).then(function (pdfPage) {
// Add div with page view.
var SCALE = 1.0;
var pdfPageView = new PDFJS.PDFPageView({
container: container,
id: id,
scale: SCALE,
defaultViewport: pdfPage.getViewport(SCALE),
// We can enable text/annotations layers, if needed
textLayerFactory: new PDFJS.DefaultTextLayerFactory(),
annotationLayerFactory: new PDFJS.DefaultAnnotationLayerFactory()
});
// Associates the actual page with the view, and drawing it
pdfPageView.setPdfPage(pdfPage);
return pdfPageView.draw();
});
}.bind(null, i));
}
return promise;
});
#container > *:not(:first-child) {
border-top: solid 1px black;
}
<link href="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.css" rel="stylesheet"/>
<script src="https://npmcdn.com/pdfjs-dist/web/compatibility.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/build/pdf.js"></script>
<script src="https://npmcdn.com/pdfjs-dist/web/pdf_viewer.js"></script>
<div id="container" class="pdfViewer singlePageView"></div>
See also How to display whole PDF (not only one page) with PDF.JS?
I have used below code to render a pdf with multiple pages.
PDFJS.disableWorker = true; // due to CORS
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d'),
pages = [],
currentPage = 1,
url = 'your_pdf.pdf';
PDFJS.getDocument(url).then(function(pdf) {
if (currentPage <= pdf.numPages) getPage();
// main entry point/function for loop
function getPage() {
// when promise is returned do as usual
pdf.getPage(currentPage).then(function(page) {
var scale = 1;
var viewport = page.getViewport(scale);
canvas.height = viewport.height;
canvas.width = viewport.width;
var renderContext = {
canvasContext: ctx,
viewport: viewport
};
// now, tap into the returned promise from render:
page.render(renderContext).then(function() {
// store compressed image data in array
pages.push(canvas.toDataURL());
if (currentPage < pdf.numPages) {
currentPage++;
getPage(); // get next page
} else {
// after all the pages are parsed
for (var i = 0; i < pages.length; i++) {
drawPage(i);
}
}
});
});
}
});
function drawPage(index, callback) {
var img = new Image;
img.onload = function() {
ctx.drawImage(this, 0, 0, ctx.canvas.width, ctx.canvas.height);
if (index > 0) img.style.display = 'inline-block';
document.body.appendChild(img);
}
img.src = pages[index]; // start loading the data-uri as source
}