JSpdf not exporting entire page by scrolling through whole content - javascript

import html2canvas from "html2canvas";
import jsPDF from "jspdf";
export function handleScreenCapture(
id,
fileName = "default",
format = "png",
isPdf = true,
resolve
) {
// document.body.scrollTop = 0;
// document.documentElement.scrollTop = 0;
// window.scrollTo(0,0);
applyShadow(false);
scrollTo(0, function () {
html2canvas(document.getElementById(id), { scale: 1 }).then((canvas) => {
applyShadow(true);
// downloadFile(canvas, fileName, format, isPdf, id);
const width = canvas.width;
const height = canvas.height;
const data = canvas.toDataURL(`image/${format}`);
const pdf = new jsPDF({
orientation: "l", // landscape
});
pdf.addImage(data, "PNG", 0, 0);
pdf.save(`${fileName}.pdf`);
});
});
}
I am using this cod to download pdf. But, it is not capturing whole page. How can i export complete page by scrolling
to bottom . I am using scrollto but not working
Please take a look

Related

Blurred pdf with pdf.js library

I'm using pdf.js library to render my pdf file on canvas.
First I was searching a solution for rendering pdf with the size of canvas parent element.
I've found it and it works fine.
Then I solve the problem of rendering ALL pages at once.
Finally, my code now looks this way:
pdfjsLib.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjsLib.version}/pdf.worker.min.js`;
class PdfLoader {
currPage = 1;
numPages = -1;
doc = null;
constructor($container) {
this.$container = $container;
}
load(path) {
// reset when using more than once
this.currPage = 1;
this.promise = new Promise(resolve => this.promiseResolve = resolve);
this.$container.innerHTML = "";
pdfjsLib.getDocument(path).promise.then(pdf => {
this.doc = pdf;
this.numPages = pdf.numPages;
pdf.getPage(1).then(this._handlePage.bind(this));
});
return this;
}
_handlePage(page) {
let viewport = page.getViewport({scale: 1});
const scale = this.$container.clientWidth/viewport.width;
// const outputScale = window.devicePixelRatio || 1;
const outputScale = 1;
viewport = page.getViewport({scale});
const cnv = document.createElement("canvas");
const ctx = cnv.getContext("2d");
const width = Math.floor(viewport.width);
const height = Math.floor(viewport.height);
cnv.width = Math.floor(width * outputScale);
cnv.height = Math.floor(height * outputScale);
cnv.style.width = `${width}px`;
cnv.style.height = `${height}px`;
const transform = (outputScale !== 1) ? [outputScale, 0, 0, outputScale, 0, 0] : null;
page.render({
canvasContext: ctx,
transform: transform,
viewport: viewport,
});
this.$container.appendChild(cnv);
this.currPage++;
if (this.doc !== null && this.currPage <= this.numPages) {
this.doc.getPage(this.currPage).then(this._handlePage.bind(this));
} else {
this.promiseResolve();
}
}
}
const $pages = document.getElementById("pages");
const pdfLoader = new PdfLoader($pages);
pdfLoader.load("extendedReport.pdf").promise
.then(initReport);
let arrow = null;
function initReport() {
// my other stuff
}
And now my problem is that when viewing rendered pdf it looks like its quality is very low and text is blurred so the document is unreadable on mobile devices. I tried to change passed scale like they say on the internet, but that's not it. Could you help me, plz? What am I missing?

How to download pdf in nuxt project?

<div style="height: 0;position: fixed; left: 50%; top: 0; transform: translateX(-50%);
z-index: -1;overflow: hidden">
<ticket-pdf v-if="pdfData" :pdfData="pdfData" :downloadBtn="downloadBtn" #download="downloadBtn = $event" /> </div>
In my nuxt project, i need to download pdf file in my main componet .When user clicked download button it will be downloaded directlty without previewing pdf component. So i hide my ticket-pdf component inside my main component . This way works in localhost but when i published my project to test area it does not work. It download only 1 empty page. and i face with this mistake.
Failed to load resource: the server responded with a status of 500 ()
If i open my pdf file in a other page and i can preview and download it also. But i need to doownload it without routing anywhere and directly in my main component
printPDF() {
const html2canvasOptions = {
allowTaint: true,
removeContainer: true,
imageTimeout: 15000,
logging: true,
useCORS: true,
scrollX: 0,
scrollY: 0,
scale: 2,
};
// Initialize the PDF.
let pdf = new jsPDF('p', 'in', [8.5, 11], false);
let totalPage = 0
//i have many pages and countof pages changes . It depends. so firstly i calculate page count and create pdf.
let pageCount = document.querySelectorAll('[id^=contentPrint]').length
for (let i = 0; i < pageCount; i++) {
const contentPrint = document.getElementById('contentPrint-' + i);
html2canvas(contentPrint, html2canvasOptions)
.then((canvas) => {
const image = {type: 'jpeg', quality: 1};
const margin = [0.5, 0.5];
let imgWidth = 8.5;
let pageHeight = 11;
let innerPageWidth = imgWidth - margin[0] * 2;
let innerPageHeight = pageHeight - margin[1] * 2;
// Calculate the number of pages.
let pxFullHeight = canvas.height;
let pxPageHeight = Math.floor(canvas.width * (pageHeight / imgWidth));
let nPages = Math.ceil(pxFullHeight / pxPageHeight);
totalPage += nPages
// Define pageHeight separately so it can be trimmed on the final page.
pageHeight = innerPageHeight;
// Create a one-page canvas to split up the full image.
let pageCanvas = document.createElement('canvas');
let pageCtx = pageCanvas.getContext('2d');
pageCanvas.width = canvas.width;
pageCanvas.height = pxPageHeight;
for (let page = 0; page <= nPages; page++) {
// Trim the final page to reduce file size.
if (page === nPages - 1 && pxFullHeight % pxPageHeight !== 0) {
pageCanvas.height = pxFullHeight % pxPageHeight;
pageHeight = (pageCanvas.height * innerPageWidth) / pageCanvas.width;
}
// Display the page.
let w = pageCanvas.width;
let h = pageCanvas.height;
pageCtx.fillStyle = 'white';
pageCtx.fillRect(0, 0, w, h);
pageCtx.drawImage(canvas, 0, page * pxPageHeight, w, h, 0, 0, w, h);
// Add the page to the PDF.
if (page > 0) pdf.addPage();
let imgData = pageCanvas.toDataURL('image/' + image.type, image.quality);
pdf.addImage(imgData, image.type, margin[1], margin[0], innerPageWidth, pageHeight);
}
});
}
setTimeout(() => {
// pdf.deletePage(totalPage + 1)
pdf.save("e-ticket" + '.pdf')
}, 3000)
setTimeout(() => {
this.$emit("download", this.download);
}, 4000)
},
This is how i create pdf area. When user clicked download button i create pdf and download it thanks to my props.
printPDF() {
window.scrollTo(0, 0);
// Initialize the PDF.
let pdf = new jsPDF('p', 'in', [8.5, 11], false);
let totalPage = 0
let counter = 0
let myArray = []
let pageCount = document.querySelectorAll('[id^=contentPrint]').length
for (let i = 0; i < pageCount; i++) {
myArray.push('contentPrint-' + i)
}
for (let i = 0; i < pageCount; i++) {
const contentPrint = document.getElementById('contentPrint-' + i);
html2canvas(contentPrint, {
scale: 2, useCORS: true, allowTaint: true, scrollY: 0
}).then((canvas) => {
.................
........
.....
counter = counter + 1;
callBack();
})
}
const callBack = () => {
if (myArray.length === counter) {
pdf.save("filename" + '.pdf')
this.$emit("download", this.download);
}
}
},
the problem was about my settimeout function . ın there ı would call pdf.save before pdf created and sure every browser works in different speed. so if we use callback function after all process done , then we can obtain our pdf rpint
You could maybe try to simply put
<a href="/your_file.csv" download>
by putting your_file.csv into the static directory.
Not sure if it can be enough in your case, sorry if it's not.

Passing Video File Input to p5js Canvas

I am trying to use Bootstrap to create a prettier interface to upload a video file rather than the p5js "createFileInput()" function. I want the video in p5js so I can overlay animations onto it. For some reason my code is displaying the video twice as soon as I use the function "createVideo" and if I try and hide the DOM that is the second video outside of the canvas it disappears from the p5js canvas. Here is my code:
var view = {
vid: "",
cHeight: 500,
cWidth: 700,
xVid: 0,
yVid: 0,
};
function setup() {
let cnv = createCanvas(view.cWidth, view.cHeight);
cnv.id("p5jsCanvas");
}
function draw() {
if (view.vid) {
// We have an uploaded video so draw it
//background(0);
console.log(view.vid.id());
image(view.vid, view.xVid, view.yVid);
} else {
background(0);
}
}
$("#videoFileUpload").on("change", function() {
var fileName = $(this).val().split("\\").pop();
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
if (this.files && this.files[0]) {
console.log(this.files[0]);
var fileLocation = URL.createObjectURL(this.files[0]);
console.log(fileLocation);
view.vid = createVideo([fileLocation], resizeVid);
view.vid.id("poseVid");
}
});
function resizeVid(){
// If the height is greater than the width use the height to scale and AUTO for the width
if (view.vid.height > view.vid.width){
console.log("height > width");
view.vid.size(AUTO, cHeight);
} else { // Else if the width is greater than or equal to the height use the width to scale and AUTO for the height
view.vid.size(view.cWidth, AUTO);
}
// Reset location of the video
let currW = $("#poseVid").attr('width');
let currH = $("#poseVid").attr('height');
view.xVid = (view.cWidth - currW)/2;
view.yVid = (view.cHeight - currH)/2;
}
I realized that I needed to use hide() on the video element and then provide a way to "play" the element in p5js and then it worked. I also added removing the id if it existed already so that I could upload a different video after one was already uploaded.
var view = {
vid: "",
cHeight: 500,
cWidth: 700,
xVid: 0,
yVid: 0,
};
function setup() {
let cnv = createCanvas(view.cWidth, view.cHeight);
cnv.id("p5jsCanvas");
}
function draw() {
if (view.vid) {
// We have an uploaded video so draw it
//background(0);
console.log(view.vid.id());
image(view.vid, view.xVid, view.yVid);
} else {
background(0);
}
}
$("#videoFileUpload").on("change", function() {
var fileName = $(this).val().split("\\").pop();
$(this).siblings(".custom-file-label").addClass("selected").html(fileName);
if (this.files && this.files[0]) {
console.log(this.files[0]);
var fileLocation = URL.createObjectURL(this.files[0]);
console.log(fileLocation);
$("#poseVid").remove(); // ADDED
view.vid = createVideo([fileLocation], resizeVid);
// view.vid.id("poseVid"); // MOVED TO resizeVid function
}
});
// ADDED FUNCTION JUST TO TEST THE PLAYBACK
function mousePressed() {
view.vid.loop(); // set the video to loop and start playing
}
function resizeVid(){
// If the height is greater than the width use the height to scale and AUTO for the width
view.vid.id("poseVid"); //MOVED INTO THIS FUNCTION
$("#poseVid").hide(); //ADDED
if (view.vid.height > view.vid.width){
console.log("height > width");
view.vid.size(AUTO, cHeight);
} else { // Else if the width is greater than or equal to the height use the width to scale and AUTO for the height
view.vid.size(view.cWidth, AUTO);
}
// Reset location of the video
let currW = $("#poseVid").attr('width');
let currH = $("#poseVid").attr('height');
view.xVid = (view.cWidth - currW)/2;
view.yVid = (view.cHeight - currH)/2;
}

Align text according to length of string

So I was working on embedding a text to pdf using the library pdf-lib in node.js. What I want to do is to embed names to a white box in pdf and align them to center according the the length of a string. firstPage.drawText is the part to align the text correctly. What I need is an algorithm to align text according the length of the string. Here's what I've tried, thanks in advance
async function loadandModPDF(name, gender) {
// Load a PDFDocument from the existing PDF bytes
const pdfDoc = await PDFDocument.load(existingPdfBytes);
pdfDoc.registerFontkit(fontkit);
const contName = await pdfDoc.embedFont(nameBold);
// Get the first page of the document
const pages = pdfDoc.getPages();
const firstPage = pages[0];
const textSize = 16;
try {
textWidth = contName.widthOfTextAtSize(name, textSize);
}
catch (e) {
console.log(e);
}
// Get the width and height of the first page
const { width, height } = firstPage.getSize();
// Draw a string of text diagonally across the first page
firstPage.drawText("John Doe" , {
x: (width - textWidth) / 3.1,
y: height - (textSize * 26),
size: textSize,
font: contName,
color: rgb(0, 0, 0),
rotate: degrees(0),
});
I have been using pdfkit. It Aligns text according to length of string automatically
import * as PDFDocument from 'pdfkit'
import getStream from 'get-stream'
const pdf = {
createPdf: async (text: string) => {
const doc = new PDFDocument()
doc.fontSize(10).text(text, 50, 50)
doc.end()
const data = await getStream.buffer(doc)
let b64 = Buffer.from(data).toString('base64')
return b64
}
}
export default pdf

How to zoom in on image of current slick slide?

I have followed https://jsfiddle.net/mkbctrll/aq9Laaew/300936/ from #mkbctrl and managed to create a slick slider but i want to zoom in on the image of the current slide.How do i implement this?
I tried using photoswipe but it doesn't work.I tried using their example but it still did not work.Other methods only have zoom in temporarily meaning when is on hover on click,the image is zoomed but it moves around with the mouse.I do not want this.What i hope to achieve is the same as CSS Zoom.
//view selected images
const fileInput = document.getElementById('my_file');
const fileList = document.getElementById('imageContainer');
let slickSettings = {
infinite: true,
draggable: false,
arrows: true,
slidesToShow: 1,
slidesToScroll: 1,
swipe: false
};
let initSlickCarousel = (target, settings) => {
const $target = $(target);
switch (true) {
case $target.hasClass('slick-initialized'):
$target.slick('unslick');
$target.slick(settings);
break;
default:
$target.slick(settings);
}
};
const handleInputChange = (event) => {
console.log('We are handling it sir!');
const filesArray = Array.from(event.target.files);
if (filesArray.length > 20) {
alert("Please select 20 or less images!!");
} else {
filesArray.map((singleFile) => {
const outputImg = document.createElement('img');
const fileReader = new FileReader();
outputImg.className = 'img-thumbnail';
// Let's read it as data url - onload won't return a thing without it
fileReader.readAsDataURL(singleFile);
fileReader.onload = (event) => {
outputImg.src = event.target.result;
};
console.log(outputImg);
console.log(event.target.files);
fileList.appendChild(outputImg);
document.getElementById("openBtn").style.pointerEvents = "none";
});
var files = event.target.files;
for (var i = 0; i < files.length; i++) {
$("#files").append('<div class="filename"><span name="fileNameList">' + files[i].name + '</span></div>');
}
if ($(".imageContainer").hasClass("slick-initialized")) {
$('.imageContainer').on('beforeChange', function (event, slick, currentSlide, nextSlide) {
$(".imageContainer").slick('slickSetOption', 'adaptiveHeight', true, true);
});
}
initSlickCarousel(fileList, slickSettings);
}
};
When I click on a zoom in button,my image that is currently displayed should zoom in.What should I do to achieve this?
UPDATE:
I have managed to do the zoom by a comment recommendation but it doesnt show the full image.This is because i set the container for my slider to 200px for both width and height.How should I make the container responsive to the currently displayed image?If i set the width to auto,it will display all the images in the slides.

Categories

Resources