Align text according to length of string - javascript

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

Related

JSpdf not exporting entire page by scrolling through whole content

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

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?

Vue how to draw picture and put next to another

i want to draw image next to another in this same div.
Generaly drawing works fine, but i have problem with placing one picture next to another.
Every time i draw image it is placend in this same div.
My HTML is:
<div id="thumbnailImages">
<canvas
id="thumbnailImage"
/>
</div>
And code:
function thumbnail(video) {
const canvasThumbnail = document.getElementById('thumbnailImage')
const cth = canvasThumbnail.getContext('2d')
const data = video.slice(8)
imgToHTML(data, e => {
const drawingThumbnail = new Image()
drawingThumbnail.src = e.target.result
drawingThumbnail.onload = function () {
canvasThumbnail.width = 128
canvasThumbnail.height = 128
cth.drawImage(drawingThumbnail, 0, 0)
document.getElementById('thumbnails').appendChild(canvasThumbnail)
}
})
}
I would like to have many 'canvas' in 'thumbnailImages' id.
Can you help me?
The issue is that you are reusing the same canvas over and over again. You need to create a new canvas to put next to it:
function thumbnail(video) {
const canvasThumbnail = document.createElement('canvas');
const cth = canvasThumbnail.getContext('2d')
const data = video.slice(8)
imgToHTML(data, e => {
const drawingThumbnail = new Image()
drawingThumbnail.src = e.target.result
drawingThumbnail.onload = function () {
canvasThumbnail.width = 128
canvasThumbnail.height = 128
cth.drawImage(drawingThumbnail, 0, 0)
document.getElementById('thumbnailImages').appendChild(canvasThumbnail)
}
})
}

User Image Upload in React without quality Loss

I'm working at a company where a File Uploader was already implemented, but for some reason we are saving the photo and its quality is greatly reduced. Basically, I want to know what the easiest way is to implement a component where a user can upload a profile photo or logo, and we can save it without losing quality. I also want to be able to resize it to various dimensions without losing quality. I don't necessarily need a cropper either, I want the user to be able to upload the photo and we display the full image, just resized without quality loss. Techstack is using JS and React.
class FileUpload extends React.Component {
constructor(props) {
super(props);
this.fileRef = createRef();
this.imgCanvas = createRef();
this.previousMoveX = 0;
this.previousMoveY = 0;
this.state = {
showUploadModal: false || props.showUploadModal,
img: '',
imgControl: false,
imgControlZoom: 0,
imgControlMove: false,
imgControlX: 0,
imgControlY: 0,
};
this.onImgRead = this.onImgRead.bind(this);
this.onChangeImage = this.onChangeImage.bind(this);
this.onChangeZoom = this.onChangeZoom.bind(this);
this.onStartMove = this.onStartMove.bind(this);
this.onMouseMove = this.onMouseMove.bind(this);
}
componentDidUpdate() {
const { img, imgControlZoom, imgControlX, imgControlY } = this.state;
if (img === '') return;
let canvas = this.imgCanvas.current;
if (canvas === null) return;
let ctx = canvas.getContext('2d');
let imgNode = new Image();
imgNode.onload = () => {
const s = parseInt(
Math.min(imgNode.width, imgNode.height) / ((imgControlZoom + 100) / 100)
);
const k = canvas.width / s;
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(
imgNode,
0,
0,
imgNode.width,
imgNode.height,
imgControlX + (s - imgNode.width) * 0.5 * k,
imgControlY + (s - imgNode.height) * 0.5 * k,
imgNode.width * k,
imgNode.height * k
);
};
imgNode.src = img;
}
onChangeImage(e) {
const input = e.target;
const { files } = e.target;
if (files === 0) return;
const file = files[0];
if (file.size > FILE_SIZE) {
toast.error(FILE_SIZE_VALIDATION);
return;
}
const fileReader = new FileReader();
fileReader.onload = ev => {
input.value = '';
this.onImgRead(ev.target.result);
};
fileReader.readAsDataURL(file, 'UTF-8');
}
This has nothing to do with React, and is not usually implemented on the client with JS, unless you are using NodeJS on the server. This feature is usually implemented on the server. Such as http_image_filter_module module of nginx.
For lossy image formats (such as jpeg), any change will again lose the quality of the image, although this loss is usually very small. If you really need to have a very high quality of the image, you need to convert them to lossless image formats (such as png) on the server first.

Loading styles from firebase firestore onto canvas error

I am trying to get data from my firestore database and use that data to create a canvas. My goal is to load a set of images and maps to return several canvases.
I am constantly getting this error:
Uncaught (in promise) TypeError: Cannot read property 'getContext' of null
I have tried using setTimeout()'s to delay the speed to help the data load quicker, but nothing seems to work.
var gImgObj;
var gMeme = [];
var gCtx;
var canvas;
function memeDivGet(theId){
setTimeout(function(){
db.collection("memeInfo").where("creator", "==", theId)
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
db.collection("memeInfo").doc(doc.id).collection("MIMG")
.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(doc) {
//alert(doc.data())
// alert("here")
console.log(doc.data().Coordinates[0].fontSize)
gMeme.push(doc.data().BaseIMG)
for (var i = 0; i < doc.data().Coordinates.length; i++) {
// alert("here" + i)
gMeme.push({
line: "line",
size: doc.data().Coordinates[i].fontSize,
align: doc.data().Coordinates[i].align,
color: doc.data().Coordinates[i].color, // in color picker, if choosing color from platte notice it stays "solid".
fontFamily: doc.data().Coordinates[i].fontStyle,
lineWidth: 2, // outline width
x: doc.data().Coordinates[i].xPos,
y: doc.data().Coordinates[i].yPos,
text: doc.data().Text[i]
})
}
//console.log(doc.data().BaseIMG)
initCanvas(doc.data().BaseIMG);
})
})
})
})
},1500)
}
function initCanvas(link) {
var canvas = document.querySelector('#canvasImage');
gCtx = canvas.getContext('2d');
gImgObj = new Image();
// console.log(link)
//alert(gMeme[0])
gImgObj.src = link;
gImgObj.onload = function () {
canvas.width = gImgObj.width;
canvas.height = gImgObj.height;
drawCanvas();
};
//console.log("HERE4")
}
function drawCanvas() {
//alert(gMeme)
gCtx.drawImage(gImgObj, 0, 0);
for (var i = 0; i < gMeme.length; i++) {
if(i > 1){
drawTxt(gMeme[i]);
}
}
for (var i = 0; i < gMeme.length - 1; i++) {
drawTxt(gMeme[i + 1]);
}
// gMeme.txts.forEach(function (txt) {
// drawTxt(txt);
// });
}
function drawTxt(txt) {
gCtx.font = txt.size + 'px' + ' ' + txt.fontFamily;
gCtx.textAlign = txt.align;
gCtx.fillStyle = txt.color;
gCtx.fillText(txt.text, txt.x, txt.y);
}
What I want to return is a set of canvases with the parameters I want.
My database is set up in this way for this section of the code:
(fooIds meaning a random id set by firebase)
Collection 'MemeInfo'
Document (fooIds)
SubCollection 'MIMG'
Document 'A'
Inside Each fooId Document, there is a creatorId which helps the computer find who created this meme, I use this to locate the document I am supposed to use for this particular creator's account.
"gMeme" is an array containing information from the database.
An "A Document" has a BaseIMG (the background image), a coordinates array with maps inside (containing the size, color, fontFamily, and other parameters), and a text array with strings inside. There is an image of an "A Document" attached.
I understand that this is quite confusing so if you have any questions please ask them in the comments section.

Categories

Resources