I'm using the current code:
const generatePDF = () => {
const input = document.getElementById("content");
const pdf = new jspdf("p", "pt", "a4");
var canvas = pdf.canvas;
canvas.width = document.body.clientWidth;
pdf.html(input, {
callback: function (pdf) {
pdf.save("mypdf.pdf");
},
});
};
that's what's happening to my pdf
I would like my text to be rightly placed on the pdf
Related
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?
I am trying to compress image size using JavaScript. but it returns canvas error.
below is my code.
var reader = new FileReader();
reader.readAsDataURL(fileItem._file);
reader.onload = function (event) {
var base64 = event.target.result.substring(event.target.result.indexOf(',') + 1, event.target.result.length);
var cvs = document.createElement('canvas');
var source_img_obj = event.target.result;
cvs.width = source_img_obj.naturalWidth;
cvs.height = source_img_obj.naturalHeight;
var ctx = cvs.getContext("2d").drawImage(source_img_obj, 0, 0);
var newImageData = cvs.toDataURL(type, 70 / 100);
var result_image_obj = new Image();
result_image_obj.src = newImageData;
console.log(result_image_obj);
};
Error:
I think you are looking something like this~
This implementation has two methods to reduce the size of the image. One method resize the image while the other compress it maintaining the same size but it reduces the quality.
This implementation is based on FileReader() to read the contents of files (or raw data buffers for Blob objects) stored on the user's computer.
// Console logging (html)
if (!window.console) console = {}
const consoleOut = document.getElementById('console-out')
console.log = message => {
consoleOut.innerHTML += message + '<br />'
consoleOut.scrollTop = consoleOut.scrollHeight
}
const outputFormat = 'jpg'
const encodeButton = document.getElementById('jpeg-encode-button')
const encodeQuality = document.getElementById('jpeg-encode-quality')
function previewFile() {
const preview = document.getElementById('source-image')
const previewResize = document.getElementById('result-resize-image')
const previewCompress = document.getElementById('result-compress-image')
const file = document.querySelector('input[type=file]').files[0]
const reader = new FileReader()
reader.onload = e => {
preview.onload = () => {
resizeFile(preview, previewResize)
compressFile(preview, previewCompress)
}
preview.src = e.target.result
// preview.src = reader.result
}
if (file) {
reader.readAsDataURL(file)
}
}
function resizeFile(loadedData, preview) {
console.log('Image resizing:')
console.log(`Resolution: ${loadedData.width}x${loadedData.height}`)
const canvas = document.createElement('canvas')
canvas.width = Math.round(loadedData.width / 2)
canvas.height = Math.round(loadedData.height / 2)
preview.appendChild(canvas)
// document.body.appendChild(canvas)
const ctx = canvas.getContext('2d')
ctx.drawImage(loadedData, 0, 0, canvas.width, canvas.height)
console.log(`New resolution: ${canvas.width}x${canvas.height}`)
console.log('---')
}
function compressFile(loadedData, preview) {
console.log('Image compressing:')
console.log(`width: ${loadedData.width} | height: ${loadedData.height}`)
const quality = parseInt(encodeQuality.value)
console.log(`Quality >> ${quality}`)
const timeStart = performance.now()
console.log('process started...')
const mimeType = typeof outputFormat !== 'undefined' && outputFormat === 'png' ? 'image/png' : 'image/jpeg'
const canvas = document.createElement('canvas')
canvas.width = loadedData.width;
canvas.height = loadedData.height;
const ctx = canvas.getContext('2d').drawImage(loadedData, 0, 0)
const newImageData = canvas.toDataURL(mimeType, quality / 100)
const img = new Image()
img.src = newImageData
preview.src = img.src
preview.onload = () => {}
const duration = performance.now() - timeStart;
console.log('process finished...')
console.log(`Processed in: ${duration}ms`)
console.log('---')
}
<input type="file" onchange="previewFile()"><br>
<div>
<h3>Original Image</h3>
<img id="source-image" />
</div>
<div>
<h3>Resized Image</h3>
<div id="result-resize-image">
</div>
</div>
<div>
<h3>Compressed Image</h3>
<img id="result-compress-image" class='img-container' />
</div>
<br><br>
<div>
<fieldset>
<legend>Compressor settings</legend>
<div id='controls-wrapper'>
Compression ratio : <input id="jpeg-encode-quality" size='3' readonly='true' type="text" value="30" /> %
</div>
</fieldset>
</div>
<div>
<fieldset>
<legend>Console output</legend>
<div id='console-out'></div>
</fieldset>
</div>
You might have to resize the canvas size
refer the following example
here
function resizeImg(base, width, height) {
var canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
var context = canvas.getContext("2d");
var deferred = $.Deferred();
$("<img/>").attr("src", "data:image/gif;base," + base).load(function() {
context.scale(width/this.width, height/this.height);
context.drawImage(this, 0, 0);
deferred.resolve($("<img/>").attr("src", canvas.toDataURL()));
});
return deferred.promise();
}
To compress a File (got from input type file) you can use this function. Just call it with the file, and it will return the same file but compressed:
const compressImage = (imageFile, quality) => {
return new Promise((resolve, reject) => {
const $canvas = document.createElement("canvas");
const image = new Image();
image.onload = () => {
$canvas.width = image.width;
$canvas.height = image.height;
$canvas.getContext("2d").drawImage(image, 0, 0);
$canvas.toBlob(
(blob) => {
if (blob === null) {
return reject(blob);
} else {
resolve(blob);
}
},
"image/jpeg",
quality / 100
);
};
image.src = URL.createObjectURL(imageFile);
});
};
Usage is:
<input type="file" id="my_input">
And JS:
const $inputFile = document.querySelector("#my_input");
$inputFile.addEventListener("change", async () => {
const file = $inputFile.files[0];
const blob = await compressImage(file, 50);
// Upload the blob with FormData or something similar
console.log({ blob });
});
I'm fetching a file from the iOS camera roll, which returns a uri in this form:
file:///var/mobile/Containers/Data/Application/90849385-6FC7-4C4E-8220-7585312C3DFB/tmp/filename.jpg
I receive this uri from this function:
function openFilePicker(selection) {
var srcType = Camera.PictureSourceType.SAVEDPHOTOALBUM;
var options = setOptions(srcType);
var func = createNewFileEntry;
navigator.camera.getPicture(function cameraSuccess(imageUri) {
loadToCanvas(imageUri);
}, function cameraError(error) {
console.debug("Unable to obtain picture: " + error, "app");
}, options);
}
and pass it to this function:
function loadToCanvas(path) {
console.log(path);
var ctx = document.getElementById('image');
ctx = ctx.getContext('2d');
var hero = new Image();
hero.onload = function () {
ctx.drawImage(hero, 0, 0);
};
hero.src = path;
}
The image is not showing in the canvas but there are no errors in the evothings console. What am I missing? Surely if cordova has the means of returning this uri to me then I should have access to the file, yeah? Thanks!
export function filter(url) {
var c = document.createElement('canvas')
c.id = "canvas_greyscale"
var canvas = new fabric.Canvas('canvas_greyscale')
fabric.Image.fromURL(url, function(oImg) {
c.height = oImg.height
c.width = oImg.width
oImg.filters.push(new fabric.Image.filters.Grayscale())
oImg.applyFilters(canvas.renderAll.bind(canvas))
canvas.add(oImg)
var img = canvas.toDataURL('image/png')
console.log(img)
return img
}, {crossOrigin: "Anonymous"})
}
Here my canvas is rendered with grayscale filter. It does not have issue but when I try to convert canvas to url it is giving me the canvas without filter.
I dont know whats wrong in here..
What am I doing wrong. I want to convert the canvas that have filter to url
var img = canvas.toDataURL('image/png') gives me image without filter
Need help
applyFilters is asynchronous (that's why you pass a renderAll callback in it).
You need to call toDataURL in its callback otherwise you're exporting the canvas before the filter is applied.
Here is a rough adaptation of your code :
function filter(url, callback) {
var c = document.createElement('canvas');
c.id = "canvas_greyscale";
var canvas = new fabric.Canvas('canvas_greyscale');
// the applyFilters' callback
var onend = function() {
canvas.renderAll();
var img = canvas.toDataURL('image/png');
callback(img);
}
fabric.Image.fromURL(url, function(oImg) {
canvas.setDimensions({width:oImg.width, height:oImg.height});
oImg.filters.push(new fabric.Image.filters.Grayscale())
// here we pass the export function
oImg.applyFilters(onend)
canvas.add(oImg)
}, {
crossOrigin: "Anonymous"
})
}
var url = 'https://upload.wikimedia.org/wikipedia/commons/5/5b/Supernumerary_rainbow_03_contrast.jpg'
filter(url, function(dataURI) {
output.src = dataURI;
original.src = url
})
img{ width: 50%}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.6.4/fabric.js"></script>
<img id="output"><br>
original Image: © Andrew Dunn CC-By-SA 2.0 <br>
<img id="original">
I am trying to generate a pdf report including current map screenshot of ESRI map using JavaScript. Here is my code.
var getCurrentMapScreenShot = function (success, error) {
esriLoader.Config.defaults.io.proxyUrl = myAppSettingsModel.SettingsModel.MapSettings.AGSProxyURL;
esriLoader.Config.defaults.io.alwaysUseProxy = true;
var printTask = new esriLoader.PrintTask("myexportUrl");
var template = new esriLoader.PrintTemplate();
template.exportOptions = {
width: 600,
height: 600,
dpi: 96
};
template.format = "image/png";
template.layout = "MAP_ONLY",
template.preserveScale = true;
template.layoutOptions = {
legendLayers: [], // empty array means no legend
scalebarUnit: "Miles"
};
var params = new esriLoader.PrintParameters();
params.map = map;
params.template = template;
printTask.execute(params, success, error);
}
This function will give you an event that contains a url , Then I am passing this url to get map base64 data.
Here is the function calling.
map.GetCurrentMapScreenShot(function (event) {
var mapScreenShotURL = event.url;
Factory.GetBase64ForImgUrl(mapScreenShotURL,
function (mapImageBase64Encoded) {});
and here is the function that converts url to base64image
function getBase64ForImgUrl(url, callback, outputFormat) {
console.log("#################### Summary Report Image " + url);
var canvas = document.createElement('CANVAS');
var ctx = canvas.getContext('2d');
var img = new Image;
img.crossOrigin = 'Anonymous';
img.onload = function () {
canvas.height = img.height;
canvas.width = img.width;
ctx.drawImage(img, 0, 0);
var dataURL = canvas.toDataURL(outputFormat || 'image/png');
callback.call(this, dataURL);
// Clean up
canvas = null;
};
img.src = url;
}
I am getting base64 image data of the map , But the problem is that, I am getting blurred image of the map with no feature layers and no icons..And also map contains some junk texts.
Thanks
I resolved the issue almost, Now I am getting the map image that contains map Icons and layer graphics, But unfortunately still getting some junk texts.
I have changed the code as follows.
template.format = "JPG";
template.layout = "A4 Landscape",
template.preserveScale = false;
template.layoutOptions = {
"legendLayers": [], // empty array means no legend
"scalebarUnit": "Miles"
}