I have a long pdf around to 6 pages that I am generation from html, and I am getting the corrupt png image error any idea how to solve this ? it happens only on ios safari
html2canvas(
document.getElementById('pdfItems')!,
{
onclone: function (clonedDoc) {
// none ! hidden show !!
clonedDoc.getElementById('pdfItems')!.style.display = 'flex';
},
// // TO INCREASE QUALITY !!!!!!!!!!
scale: /*3*/ 2,
}
).then((canvas) => {
//document.body.appendChild(canvas); // if you want see your screenshot in body.
const imgData = canvas.toDataURL('image/png');
//A4
var imgWidth = 210;
// PAGE height in px !!!!!!!!!!!!!!!!!!
var pageHeight = 295;
// ???????? 2500 * 210 / 1140
var imgHeight = (canvas.height * imgWidth) / canvas.width;
// ????????
var heightLeft = imgHeight;
// A4
var doc = new jsPDF('p', 'mm', 'a4', true);
var topPadding = 10; // give some top padding to first page
doc.addImage(imgData, 'PNG', 0, topPadding, imgWidth, imgHeight);
// is the image bigger than the page ??? image hight is bigger than pdf page !!
heightLeft -= pageHeight;
while (heightLeft >= 0) {
topPadding = heightLeft - imgHeight; // Starting position to continue from
doc.addPage();
doc.addImage(imgData, 'PNG', 0, topPadding, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
doc.save(`${fileName()}.pdf`);
setTimeout(() => _backdropContext.SetBackDrop(false), 500);
});
};
Related
I wanted to upload the image files, draw them into canvas, make changes and save it in the database. I tried to test the base64 value that the canvas image (Pic) returned, and it is blank. However, I see the result when I append the canvas (Pic) to the document. What am I doing wrong here?
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
// read contents of files asynchronously
var reader = new FileReader();
// Closure to capture the file information.
reader.onload = (function(theFile) {
return function(e) {
var canvas = document.createElement("canvas");
var datauri = event.target.result,
ctx = canvas.getContext("2d"),
img = new Image();
img.onload = function() {
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
};
img.src = datauri;
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
document.body.appendChild(canvas); //picture gets uploaded
// Generate the image data
var Pic = canvas.toDataURL("image/png");
console.log(Pic); // => returns base64 value which when tested equivalent to blank
Pic = Pic.replace(/^data:image\/(png|jpg);base64,/, "")
// Sending image to Server
$.ajax({
// …
});
};
})(f);
reader.readAsDataURL(f);
}
}
My intuition says that everything from var imageData = … should go into the img.onload function.
That means, at the relevant part the code becomes:
img.onload = function() {
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0, width, height);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
document.body.appendChild(canvas); //picture gets uploaded
// Generate the image data
var Pic = canvas.toDataURL("image/png");
console.log(Pic); // => returns base64 value which when tested equivalent to blank
Pic = Pic.replace(/^data:image\/(png|jpg);base64,/, "")
// Sending image to Server
$.ajax({
// …
});
};
img.src = datauri;
The reason is that the line
ctx.drawImage(img, 0, 0, width, height);
correctly executes after the image has been loaded. But unfortunately, you don’t wait for loading when this line gets executed:
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
and all subsequent lines.
The image needs to be loaded in order to draw it on the canvas. The canvas needs to contain the loaded image in order to call getImageData.
I found a better solution to get the base64 code
Instead of this line:
var Pic = canvas.toDataURL("image/png");
use this:
var Pic = canvas.toDataURL("image/png").split(',')[1];
When I click on the spin button, I want the value to be highlighted one by one in the canvas.
Here you can see the whole code: https://codesandbox.io/s/spinning-wheel-react-forked-s528m
renderWheel() {
// determine number/size of sectors that need to created
let numOptions = this.state.list.length;
let arcSize = (2 * Math.PI) / numOptions;
this.setState({
angle: arcSize
});
// dynamically generate sectors from state list
let angle = 0;
for (let i = 0; i < numOptions; i++) {
let text = this.state.list[i];
this.renderSector(i + 1, text, angle, arcSize);
angle += arcSize;
}
}
renderSector(index, text, start, arc) {
// create canvas arc for each list element
let canvas = document.getElementById("wheel");
let ctx = canvas.getContext("2d");
let x = canvas.width / 2;
let y = canvas.height / 2;
let radius = 200;
let startAngle = start;
let endAngle = start + arc - 0.02;
let angle = index * arc;
let baseSize = radius * 1.25;
let textRadius = baseSize - 48;
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle, false);
ctx.lineWidth = radius * 0.25;
ctx.strokeStyle = "white";
ctx.font = "25px Arial";
ctx.fillStyle = "blue";
ctx.stroke();
ctx.save();
ctx.translate(
baseSize + Math.cos(angle - arc / 2) * textRadius,
baseSize + Math.sin(angle - arc / 2) * textRadius
);
ctx.rotate(0);
ctx.fillText(text, -ctx.measureText(text).width / 2, 7);
ctx.restore();
}
When I click on the spin button, this spin () method is executed.
The iteration ends between two and five seconds as written in the setTimeout method.
spin = () => {
var index = 0;
let timer = setInterval(() => {
index = (index) % this.state.list.length + 1;
console.log(index)
}, 150);
// calcalute result after wheel stops spinning
setTimeout(() => {
clearInterval(timer);
this.setState({
hasFinishedLoading: true,
display: this.state.list[index]
});
}, Math.floor(Math.random() * 5000 + 2000));
this.setState({
spinning: true
});
};
Remember: In canvas you cannot access a particular object, so the solution is always to erase and redraw. Don't worry about performance, this is pretty great. I leave you an idea with your code and at the end some suggestions. Try this code, the only thing I did is clean the canvas and redraw without the setTimeOut index
spin = () => {
let canvas = document.getElementById("wheel");
let ctx = canvas.getContext("2d");
var index = 0;
index = (index % this.state.list.length) + 1;
let angle = 0;
let numOptions = this.state.list.length;
let arcSize = (2 * Math.PI) / numOptions;
let timer = setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
this.setState({
angle: arcSize
});
for (let i = 0; i < numOptions; i++) {
if (i !== index) {
let text = this.state.list[i];
this.renderSector(i + 1, text, angle, arcSize);
angle += arcSize;
} else {
}
}
}, 150);
// calcalute result after wheel stops spinning
setTimeout(() => {
clearInterval(timer);
this.setState({
hasFinishedLoading: true,
display: this.state.list[index]
});
}, Math.floor(Math.random() * 5000 + 2000));
this.setState({
spinning: true
});
};
Don't use "getElementById" in react, it's dangerous. Use a reference.
Providing code snippet of generating pdf file.
Im trying to get an table converted into Pdf. To do that im using html2canvas and creating image of that table.
Image is getting inside of the pdf but im not getting any image break at the end of pdf page. Need space ta bottom and top of each page.
I also need to add a title at the top of each page.
html2canvas($("#LogBookReport"), {
onrendered: function (canvas) {
var imgData = canvas.toDataURL('image/png');
var imgWidth = 200;
var pageHeight = 290;
var imgHeight = canvas.height * imgWidth / canvas.width;
var heightLeft = imgHeight;
var doc = new jsPDF('p', 'mm','a4');
var position = 40;
doc.addImage($scope.PdfPrintData.img,'PNG',5,3,20,20);// adding logo on first page
doc.setFontSize(15);
doc.text(80, 15, 'Teaching Log - Report ');// page titile
doc.setFontSize(9);
doc.text(10, 25, 'Branch Name: ');//static data
doc.setFontSize(9);
doc.text(150, 25, 'Date: ' );//static data
doc.setFontSize(9);
doc.text(10, 30, 'Teacher Name: ');//static data
doc.setFontSize(9);
doc.text(10, 35, 'Downloded By: ');//static data
doc.setFontSize(9);
doc.addImage(imgData, 'PNG', 5, position, imgWidth, imgHeight);// adding table image
heightLeft -= pageHeight;
while (heightLeft >= 0) {
doc.addPage();
position = heightLeft - imgHeight+40;
doc.addImage(imgData, 'PNG',5, position, imgWidth, imgHeight);
heightLeft -= pageHeight;
}
if (confirm("Are you sure do you want to download this file ")) {
filename = " LogBook Report "+'.pdf';
doc.save(filename);
}
}
});
I am working on a multipage pdf download using html2canvas and pdfmake.
I am able to download the pdf but page height, page width of the generated pdf is not proper and the resolution is low/blur. The code is as below. Please refer the screenshot attached herewith.
Thanks in advance.
Code I have used is:
html2canvas(document.getElementById('newId')).then(
canvas=>{
var image = canvas.toDataURL('image/png');
const PAGE_WIDTH = 500;
const PAGE_HEIGHT = 700;
const content = [];
var w=500;
var h=700;
function getPngDimensions (base64) {
const header = atob(base64.slice(22, 70)).slice(16, 24);
const uint8 = Uint8Array.from(header, c => c.charCodeAt(0));
const dataView = new DataView(uint8.buffer);
return {
width: dataView.getInt32(0),
height: dataView.getInt32(4)
};
}
const splitImage = (img, content, callback) => () => {
const canvas = document.createElement('canvas');
canvas.width = w*2;
canvas.height=h*2;
canvas.style.width=w+'px';
canvas.style.height=h+'px';
const ctx = canvas.getContext('2d');
ctx.scale(2,2);
const printHeight = img.height * PAGE_WIDTH / img.width;
for (let pages = 0; printHeight > pages * PAGE_HEIGHT; pages++) {
canvas.height = Math.min(PAGE_HEIGHT, printHeight - pages * PAGE_HEIGHT);
ctx.drawImage(img, 0, -pages * PAGE_HEIGHT, img.width, printHeight);
content.push({ image: canvas.toDataURL(), margin: [0, 5],width:PAGE_WIDTH });
}
callback();
};
function next () {
pdfMake.createPdf({ content }).open();
}
const { width, height } = getPngDimensions(image);
const printHeight = height * PAGE_WIDTH / width;
if (printHeight > PAGE_HEIGHT) {
const img = new Image();
img.onload = splitImage(img, content, next);
img.src = image;
return;
}
content.push({ image, margin: [0, 5], width: PAGE_WIDTH });
next();
}
);
Update:
I tried updating the width and height of the image formed by the canvas but increasing the width onl increases the pixel size and further truncates the right end of the dashboard.
const PAGE_WIDTH = 500;
const PAGE_HEIGHT = 700;
//some more code here as mentioned in the detailed snippet
const content = [];
var w=500;
var h=700;
Poor Pixel Display For Multi Page PDF Through Banana Dashboard
I have background image on background of canvas. And i want to put another image on background image. SO i can rotate upward image in any direction. I am trying javascript code which is available on internet. But both images were rotated. I want to rotate only upward image with some angle.
/* Upload first image to 0,0 co-ordinate. */
ctx.beginPath();
var imageObj = new Image();
imageObj.onload = function()
{
ctx.drawImage(imageObj, 0, 0, 300, 150);
};
imageObj.src = 'C://Users//rajesh.r//Downloads//images//images.jpg';
options.ctx.fill();
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
ctx.beginPath();
ctx.translate(400,300);
ctx.rotate(2*Math.PI / 8);
var thumbImageObj = new Image();
thumbImageObj.onload = function()
{
ctx.drawImage(thumbImageObj, 0, 0, 120, 20);
};
thumbImageObj.src = 'C://Users//rajesh.r//Downloads//images//images.png';
ctx.fill();
I want some solution so i can rotate second image by some angle.
When you call rotate on your canvas, you're not rotating an individual image, but instead rotating the entire canvas. To only rotate the second image you need take advantage of the save and restore methods provided by the canvas API.
Here's an example, based off of the code that you shared:
// canvas setup
var canvas = document.getElementById('canvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext('2d');
// 1st image
var imageObj = new Image();
imageObj.onload = function() {
ctx.drawImage(imageObj, 0, 0, 100, 100);
};
imageObj.src = 'https://s3.amazonaws.com/so-answers/image1.jpg';
// 2nd image
var thumbImageObj = new Image();
thumbImageObj.onload = function() {
// save current canvas state
ctx.save();
// perform transformation
ctx.translate(110,110);
ctx.rotate(20*Math.PI / 180);
ctx.drawImage(thumbImageObj, 0, 0, 100, 100);
// restore original canvas state (without rotation etc)
ctx.restore();
};
thumbImageObj.src = 'https://s3.amazonaws.com/so-answers/image2.jpg';
body {
overflow: hidden;
margin: 0;
padding: 0;
}
<canvas id="canvas"></canvas>