In my controller I am defining html2canvas functions like:
var builderApp = angular.module('builderApp',
['fg', 'ngSanitize', 'ui.bootstrap', 'angularFileUpload', 'textAngular', 'ui.grid', 'ui.grid.pagination']);
builderApp
.run(function ($templateCache) {
$templateCache.put('custom-busy.html',
"<div class=\"cssload-loader\"><div class=\"cssload-inner cssload-one\"></div><div class=\"cssload-inner cssload-two\"></div><div class=\"cssload-inner cssload-three\"></div></div>"
);
});
builderApp.controller('builderCtrl', function ($scope, formSchema, formData, $http, $filter) {
var vm = this;
$scope.canvasToImageSuccess = function (canvas) {
var margins = {
top: 50,
bottom: 80,
left: 20,
width: 600
};
var pdf = new jsPDF('p', 'pt', 'a4'), // jsPDF(orientation, unit, format)
pdfInternals = pdf.internal,
pdfPageSize = pdfInternals.pageSize,
pdfScaleFactor = pdfInternals.scaleFactor,
pdfPageWidth = pdfPageSize.width - (margins.left + margins.left),
pdfPageHeight = pdfPageSize.height + margins.left,
totalPdfHeight = 0,
htmlPageHeight = canvas.height,
htmlScaleFactor = canvas.width / (pdfPageWidth * pdfScaleFactor),
safetyNet = 0;
pdf.setFontSize(22);
pdf.setFontStyle('italic');
pdf.page = 1;
while (totalPdfHeight < htmlPageHeight && safetyNet < 15) {
var newCanvas = canvasShiftImage(canvas, totalPdfHeight);
pdf.addImage(newCanvas, 'png', margins.left, margins.top, pdfPageWidth, 0, null, 'NONE');
pdf.page++;
totalPdfHeight += (pdfPageHeight * pdfScaleFactor * htmlScaleFactor);
if (totalPdfHeight < htmlPageHeight) {
pdf.addPage();
}
safetyNet++;
}
pdf.save(fileName);
};
$scope.createPDF = function () {
var source = $("#formData").html();
var fileName = "Form1.Pdf";
var canvasToImage = function (canvas) {
var img = new Image();
var dataURL = canvas.toDataURL('image/png');
img.src = dataURL;
return img;
};
var canvasShiftImage = function (oldCanvas, shiftAmt) {
shiftAmt = parseInt(shiftAmt) || 0;
if (!shiftAmt) { return oldCanvas; }
var newCanvas = document.createElement('canvas');
newCanvas.height = oldCanvas.height - shiftAmt;
newCanvas.width = oldCanvas.width;
var ctx = newCanvas.getContext('2d');
var img = canvasToImage(oldCanvas);
ctx.drawImage(img, 0, shiftAmt, img.width, img.height, 0, 0, img.width, img.height);
return newCanvas;
};
try{
html2canvas(source, {
onrendered: function (canvas) {
alert('rendered');
$scope.canvasToImageSuccess(canvas);
}
});
}
catch(e)
{
var x = e;
}
}
From UI I am able to call createPDF function however, the alert in html2canvas is not getting fired and so my function canvasToImageSuccess does not get executed.
Am I missing anything here?
I tried to inject html2canvas as global.html2canvas = require("html2canvas"); but this is not working.
I checked console, but there is not error.
The fix was that the html2canvas needs element and not the html text.
so, line:
html2canvas(source,
should be:
html2canvas($("#formData"),
Related
I've a webpage with 4 charts. I'm taking separate screenshots for each of them. Then tried to put them on another canvas, show them vertically and print it as single-page pdf file. But, I'm getting an Error saying:
Uncaught TypeError: CanvasRenderingContext2D.drawImage: Argument 1
could not be converted to any of: HTMLImageElement, SVGImageElement,
HTMLCanvasElement, HTMLVideoElement, ImageBitmap.
Here is the script
function HTMLtoPDF() {
function verticalCanvases(cnv1, cnv2, cnv3, cnv4) {
var newCanvas = document.createElement('canvas'),
ctx = newCanvas.getContext('2d'),
width = cnv1.width,
height = cnv1.height + cnv2.height + cnv3.height + cnv4.height;
newCanvas.width = width;
newCanvas.height = height;
[{
cnv: cnv1,
y: 0
},
{
cnv: cnv2,
y: cnv1.height
},
{
cnv: cnv3,
y: cnv1.height + cnv2.height
},
{
cnv: cnv4,
y: cnv1.height + cnv2.height + cnv3.height
}].forEach(function(n) {
ctx.beginPath();
ctx.drawImage(n.cnv, 0, n.y, width, n.cnv.height);
});
var imgdata = newCanvas.toDataURL();
return imgdata;
}
var forms = $('[id^=caspioform]');
var canvas1 = html2canvas(forms[3]);
var canvas2 = html2canvas(forms[5]);
var canvas3 = html2canvas(forms[7]);
var canvas4 = html2canvas(forms[9]);
var dURL = verticalCanvases(canvas1, canvas2, canvas3, canvas4);
var doc = new jsPDF("p", "mm", "a4");
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
doc.addImage(dURL, 'PNG', 0, 0, width, height);
doc.save('sample.pdf');
}
Since you didn't mention it, I'll assume html2canvas is coming from https://github.com/niklasvh/html2canvas
In that case, the issue here is that hmtl2canvas returns a Promise and that's what you're passing to verticalCanvases instead of the actual canvas element.
To fix it just transform the function in an asynchronous one so you can use async/await:
// |
// |
// v
async function HTMLtoPDF() {
function verticalCanvases(cnv1, cnv2, cnv3, cnv4) {
var newCanvas = document.createElement('canvas'),
ctx = newCanvas.getContext('2d'),
width = cnv1.width,
height = cnv1.height + cnv2.height + cnv3.height + cnv4.height;
newCanvas.width = width;
newCanvas.height = height;
[{
cnv: cnv1,
y: 0
},
{
cnv: cnv2,
y: cnv1.height
},
{
cnv: cnv3,
y: cnv1.height + cnv2.height
},
{
cnv: cnv4,
y: cnv1.height + cnv2.height + cnv3.height
}].forEach(function(n) {
ctx.beginPath();
ctx.drawImage(n.cnv, 0, n.y, width, n.cnv.height);
});
var imgdata = newCanvas.toDataURL();
return imgdata;
}
var forms = $('[id^=caspioform]');
var canvas1 = await html2canvas(forms[3]); // <--
var canvas2 = await html2canvas(forms[5]); // <--
var canvas3 = await html2canvas(forms[7]); // <--
var canvas4 = await html2canvas(forms[9]); // <--
var dURL = verticalCanvases(canvas1, canvas2, canvas3, canvas4);
var doc = new jsPDF("p", "mm", "a4");
var width = doc.internal.pageSize.getWidth();
var height = doc.internal.pageSize.getHeight();
doc.addImage(dURL, 'PNG', 0, 0, width, height);
doc.save('sample.pdf');
}
I've been trying to printed page as pdf , but haven't been able to, which causes the error : object doesn't support property or method 'setattribute'
at line ; html2canvas($(html)).find('#Content')[0],
How to fix error ?
window.onload = function() {
document.getElementById("cmd").onclick = function fun() {
alert("hello");
exportTwo();
}
}
function exportTwo() {
var canvasToImage = function(canvas){
var img = new Image();
var dataURL = canvas.toDataURL('image/png');
img.src = dataURL;
return img;
};
var canvasShiftImage = function(oldCanvas,shiftAmt){
shiftAmt = parseInt(shiftAmt) || 0;
if(!shiftAmt){ return oldCanvas; }
var newCanvas = document.createElement('canvas');
newCanvas.height = oldCanvas.height - shiftAmt;
newCanvas.width = oldCanvas.width;
var ctx = newCanvas.getContext('2d');
var img = canvasToImage(oldCanvas);
ctx.drawImage(img,0, shiftAmt, img.width, img.height, 0, 0, img.width, img.height);
return newCanvas;
};
var canvasToImageSuccess = function(canvas){
var pdf = new jsPDF('l','px'),
pdfInternals = pdf.internal,
pdfPageSize = pdfInternals.pageSize,
pdfScaleFactor = pdfInternals.scaleFactor,
pdfPageWidth = pdfPageSize.width,
pdfPageHeight = pdfPageSize.height,
totalPdfHeight = 0,
htmlPageHeight = canvas.height,
htmlScaleFactor = canvas.width / (pdfPageWidth * pdfScaleFactor),
safetyNet = 0;
while(totalPdfHeight < htmlPageHeight && safetyNet < 15){
var newCanvas = canvasShiftImage(canvas, totalPdfHeight);
pdf.addImage(newCanvas, 'png', 0, 0, pdfPageWidth, 0, null, 'NONE');
totalPdfHeight += (pdfPageHeight * pdfScaleFactor * htmlScaleFactor);
if(totalPdfHeight < htmlPageHeight){
pdf.addPage();
}
safetyNet++;
}
pdf.save('test.pdf');
};
$.ajax({
url:'https://apps.group.ec/sites/Insight/en-us/Pages/Dom/dm.aspx',
type:'GET',
success: function(data){
//$('#Content').html($(data).find('#content').html());
var html = $.parseHTML(data);
console.log($(html).find( '#Content').html());
html2canvas($(html)).find('#Content')[0], {
onrendered: function(canvas){
canvasToImageSuccess(canvas);
}
};
}
});
}
Thank you.
I'm having a problem trying to use JSPdf with Vuejs. I've got a tutorial on the internet (this one) that shows how to print all the contents of a div (because it was not possible.) But the test works perfectly, in mine, even if I can adapt, the PDF comes in blank, can anyone help?
My code adapted with VueJS:
methods: {
GerarPdf(){
let source = $('#div')
let cache_width = source.width()
let a4 = [595.28, 990.89]
let canvasImage = ''
let winHeight = a4[1]
let formHeight = source.height()
let formWidth = source.width()
let imagePieces = []
imagePieces = [];
imagePieces.length = 0;
source.width((a4[0] * 1.33333) - 80).css('max-width', 'none');
return html2canvas(source, {
imageTimeout: 2000,
removeContainer: true
})
.then(canvas => {
console.log(canvas)
canvasImage = new Image();
canvasImage.src = canvas.toDataURL("image/png");
let totalImgs = Math.round(formHeight/winHeight);
for(let i = 0; i < totalImgs; i++) {
let canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
canvas.width = formWidth;
canvas.height = winHeight;
ctx.drawImage(canvasImage, 0, i * winHeight, formWidth, winHeight, 0, 0, canvas.width, canvas.height);
imagePieces.push(canvas.toDataURL("image/png"));
}
console.log(imagePieces.length);
let totalPieces = imagePieces.length - 1;
let doc = new jsPDF({
unit: 'px',
format: 'a4'
});
imagePieces.forEach(function(img){
doc.addImage(img, 'JPEG', 20, 40);
if(totalPieces)
doc.addPage();
totalPieces--;
});
doc.save('techumber-html-to-pdf.pdf');
//source.width(cache_width);
})
}
}
I want to access an object but I don't know how.
I want to access 'ctx', but using base.ctx always returns null (is this a closure?).
window.base = function () {
var c = null,
ctx = null;
window.addEventListener("load", function(){
c = document.getElementById("canvas");
ctx = c.getContext("2d");
}
}
I found the solution was to call a function in base that returned ctx.
window.base = function () {
var c = null,
ctx = null;
window.addEventListener("load", function(){
c = document.getElementById("canvas");
ctx = c.getContext("2d");
}
return {
ctx: function(){return ctx;}
};
}
Then I can access ctx, but now all my accesses need to be:
base.ctx().setStyle = "white";
Rather than what I'd like which is:
base.ctx.setStyle = "white";
Is it possible? I'm thinking there's a possible solution with 'this'/scope or something, but I don't know enough JavaScript yet.
base is a function.
use it like this:
base().ctx()
I would write your code in this way:
window.addEventListener('load', function () {
var base = function () {
return document.getElementById("canvas").getContext("2d");
}
// Do something with base()
});
You can also drop the function and just use the context:
window.addEventListener('load', function () {
var base = document.getElementById("canvas").getContext("2d");
// Do something
});
The answer for me was to store the values in an object called "inter", and then update the contents of that object - the changes were then visible to other code.
So then I could use:
base.ctx.fillStyle = "white";
I have no idea why the other way didn't work!
var base = function () {
var fps = 60,
canvasWidth = 300,
canvasHeight = 200,
scaling = 1;
function updateCanvas(){
ctx.putImageData(imageData, 0, 0);
}
var c = null,
cStyle = null,
updateGraphicsCallBack = null;
function initialiseCanvas(canvasName, theCallBack){
updateGraphicsCallBack = theCallBack;
c = document.getElementById(canvasName);
cStyle = c.style;
inter.ctx = c.getContext("2d");
inter.imageData = inter.ctx.getImageData(0, 0, canvasWidth, canvasHeight);
inter.imageArray = inter.imageData.data;
inter.buff8 = new Uint8ClampedArray(inter.imageArray.buffer);
inter.buff32 = new Uint32Array(inter.imageArray.buffer);
cStyle.width = canvasWidth * scaling + "px";
cStyle.height = canvasHeight * scaling + "px";
c.width = canvasWidth;
c.height = canvasHeight;
inter.ctx.imageSmoothingEnabled = true;
inter.ctx.fillStyle="#909090";
//mouse = (typeof window.mouseInit !== "undefined") ? window.mouseInit(c) : null;
//if(typeof window.db !== "undefined") window.db.setOutput("debugOutput");
requestAnimationFrame(drawLoop);
}
var oldTimeStamp = 0, timeTweak = 0;
function drawLoop(currentTimeStamp) {
currentTime = currentTimeStamp;
if(typeof timeChart !== "undefined") timeChart.start();
setTimeout(
function() {
requestAnimationFrame(drawLoop);
}, (1000 - ((currentTimeStamp - oldTimeStamp) - timeTweak)) / fps);
updateGraphicsCallBack(currentTimeStamp);
if(typeof timeChart !== "undefined") {
timeChart.end();
if(timeChart.currentFrameCount() > -1){
var difference = timeChart.currentFrameCount() - fps;
timeTweak += difference;
if(timeTweak<-10000) timeTweak = -10000;
if(timeTweak>10000) timeTweak = 10000;
}
inter.timeTweak = timeTweak;
}
oldTimeStamp = currentTimeStamp;
}
var inter = {
updateCanvas: updateCanvas,
ctx: null,//function(){return ctx;},
canvasWidth: canvasWidth,
canvasHeight: canvasHeight,
fps: fps,
scaling: scaling,
imageData: null,
imageArray: null,
buff8: null,
buff32: null,
timeTweak: timeTweak,
initialiseCanvas: initialiseCanvas
};
return inter;
}();
Im trying to drag and drop an image in canvas. But when dragging in chrome the image disapears but in Mozilla it works fine. Any help on this would be really appreciated.
HTML File
<head>
<script>
var canvasImages = [];
function imageProp() {
this.imgName = ' ';
this.imgX = 0;
this.imgY = 0;
this.ImgWidth = 1;
this.ImgHeight = 1;
}
function GetFilename(url) {
if (url) {
var m = url.toString().match(/.*\/(.+?)\./);
if (m && m.length > 1) {
return m[1];
}
}
return "";
}
function load(source) {
var canvas = document.getElementById("mycanvas");
var ctx = canvas.getContext('2d');
var imageObj = new Image();
//Loading image to Canvas
imageObj.onload = function () {
ctx.drawImage(imageObj, 0, 0);
};
imageObj.src = source;
//Inserting properties of image loaded in canvas to an array
var Property = new imageProp;
//Property.imgName = GetFilename(source);
Property.imgName = source;
Property.imgX = 0;
Property.imgY = 0;
Property.ImgWidth = imageObj.width;
Property.ImgHeight = imageObj.height;
canvasImages.push(Property);
}
</script>
</head>
<body>
<img id = "imgID" onclick=" load(this.src)" src = 'download.png'/>
<canvas id="mycanvas" width="1000" height="1000">HTML5 Not Supported</canvas>
<script src="Canvas_js.js"></script>
</body>
Javascript file
(function () {
"use strict";
/*global document*/
/*global clear*/
/*global canvasImages*/
/*jslint devel: true */
/*jslint browser: true */
var canvas, ctx, ghostcanvas, gctx, RedrawInterval = 20, canvasValid = false, clickLoc = {}, isDragging = false, index = 0, selectedIndex = 0;
clickLoc.x = 0;
clickLoc.y = 0;
function drawCanv() {
var i = 0, imageObj;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (i = 0; i < canvasImages.length; i += 1) {
imageObj = new Image();
imageObj = document.createElement('img');
imageObj.src = canvasImages[i].imgName;
imageObj.onload = function () {
ctx.drawImage(imageObj, canvasImages[i].imgX, canvasImages[i].imgY);
};
}
}
function resizeHandler(index) {
ctx.beginPath();
ctx.strokeRect(canvasImages[index].imgX, canvasImages[index].imgY, canvasImages[index].ImgWidth + 5, canvasImages[index].ImgHeight + 5);
}
function canvasOnClick(e) {
var rect, i = 0;
isDragging = true;
//Get X and Y coordinates of the click
rect = canvas.getBoundingClientRect();
clickLoc.x = e.clientX - rect.left;
clickLoc.y = e.clientY - rect.top;
//Check whether any image is clicked
for (i = 0; i < canvasImages.length; i += 1) {
if (clickLoc.x >= canvasImages[i].imgX && clickLoc.x <= canvasImages[i].imgX + canvasImages[i].ImgWidth && clickLoc.y >= canvasImages[i].imgY && clickLoc.y <= canvasImages[i].imgY + canvasImages[i].ImgHeight) {
selectedIndex = i;
resizeHandler(i);
}
}
}
function canvasMouseUp(e) {
isDragging = false;
}
function canvasMouseMove(e) {
if (isDragging === true) {
canvasImages[selectedIndex].imgX += 5;
drawCanv();
}
}
function init() {
// Defining Canvas and fake canvas
canvas = document.getElementById('mycanvas');
ctx = canvas.getContext('2d');
ghostcanvas = document.createElement('canvas');
ghostcanvas.height = canvas.height;
ghostcanvas.width = canvas.width;
gctx = ghostcanvas.getContext('2d');
// Redrawing canvas for the interval
//setInterval(draw, RedrawInterval);
// Adding Eventlisteners
canvas.addEventListener("mousedown", canvasOnClick, false);
canvas.addEventListener("mouseup", canvasMouseUp, false);
canvas.addEventListener("mousemove", canvasMouseMove, false);
}
init();
}());
Start messing around with
user-select: none;
-webkit-user-select: none;
in your css.