Get canvas toDataUrl() after processing Javascript - javascript

I have a Javascript function that create a canvas, write a image and a text on it. At the and I need the base64 dataUrl but what I get is only a blank canvas.
This is my function:
function createBreadCrumb(label) {
var canvas = document.createElement('canvas');
canvas.width = 25;
canvas.height = 30;
var img = new Image;
img.src = 'map-pin-breadcrumb.png';
var ctx=canvas.getContext("2d");
img.onload = function(){
ctx.drawImage(img, 0, 0);
ctx.font = "11px Arial";
ctx.textAlign="center";
ctx.fillText(label, 12, 16);
};
return canvas.toDataURL();
}

You are calling toDataURL before the image is loaded. As a result, none of your canvas instructions have run yet. Because the image is loaded asynchronously, you cannot get the resulting canvas synchronously and must use a callback or a promise.
Try this.
function createBreadCrumb(label, callback) {
var canvas = document.createElement('canvas');
canvas.width = 25;
canvas.height = 30;
var img = new Image;
var ctx = canvas.getContext("2d");
img.onload = function(){
ctx.drawImage(img, 0, 0);
ctx.font = "11px Arial";
ctx.textAlign="center";
ctx.fillText(label, 12, 16);
callback(canvas.toDataURL());
};
img.src = 'map-pin-breadcrumb.png';
}
createBreadCrumb("hello", function(crumb){
// do your stuff
});

Related

dataURL not working when the context of the canvas is an image

i was trying to download the context of the canvas as an image using dataURL() through the following code but it's not working for some reason. However, when i replace the context of the canvas to be something else besides the image it actually works, so can you tell how can i fix this
<a href="#" id="downloader" >Download!</a>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var image = new Image(60, 45);
image.onload = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
ctx.drawImage(image, 0, -60);
}
image.src = 'image.png';
$('#downloader').click(function(){
$(this).attr('href', document.getElementById('canvas').toDataURL("image/png").replace("image/png", "image/octet-stream"));
$(this).attr('download', "Picture.png");
});
</script>
Your JS should be:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var image = new Image(60, 45);
//First add src, then set the height and width
image.src = 'image.png';
image.onload = function() {
canvas.width = image.width;
canvas.height = image.height;
// Draw image from start and not from behind the axis
ctx.drawImage(image, 0, 0);
}
$('#downloader').click(function() {
$(this).attr('href', document.getElementById('canvas').toDataURL("image/png"))
$(this).attr('download', "Picture.png");
});

image onload not triggering inside of promise

Hello I created a promise and call it recursively from a loop to fill an array but the onload never triggers thus never resolving the promise.
Can anyone see anything I'm doing wrong?
function imageResizeToDataUriPromise(url, width, height) {
return new Promise(function (resolve, reject) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function () {
var imgWidth = img.naturalWidth;
var imgHeight = img.naturalHeight;
var result = _scaleImage(imgWidth, imgHeight, width, height, true);
//create an off-screen canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = result.width;
canvas.height = result.height;
//draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, result.width, result.height);
resolve(canvas.toDataURL());
};
img.src = url;
});
}
this is my basic calling block but its in a loop
caller(logo, 150, 150).then
(function (response) {
console.log("Success!", response);
base64Urls.push(response);
});
It works after I use that promise to get an URL and set it to an image element... not sure how you would use the return Data URL. One possible issue is: can you check whether your image source is serving you the image. (double check the network tab in developer tool).
function imageResizeToDataUriPromise(url, width, height) {
return new Promise(function(resolve, reject) {
var img = new Image();
img.setAttribute('crossOrigin', 'anonymous');
img.onload = function() {
console.log("IMG ONLOAD handler invoked");
var imgWidth = img.naturalWidth;
var imgHeight = img.naturalHeight;
var result = img;
//create an off-screen canvas
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
canvas.width = result.width;
canvas.height = result.height;
//draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, result.width, result.height);
ctx.fillStyle = "white";
ctx.font = '21px sans-serif';
ctx.fillText('Hello world', 21, 51);
resolve(canvas.toDataURL());
};
img.src = url;
});
}
imageResizeToDataUriPromise("https://i.imgur.com/j7Ie7pg.jpg", 100, 100)
.then(url => document.querySelector("#an-image").src = url);
console.log("Promise obtained");
<img id="an-image">

Drawing ends up all black

I'm trying to resize an image via HTML canvas, but when I display it, it displays all black.
My code
function onSuccess(imageData) {
var img = new Image();
img.src = imageData;
window.setTimeout(function() {
var maxSize = 200;
var canvas = document.createElement("canvas");
canvas.width = maxSize;
canvas.height = maxSize;
var ctx = canvas.getContext("2d");
ctx.drawImage(img.src, 0, 0, maxSize, maxSize);
dataurl = canvas.toDataURL("image/jpeg");
alert(dataurl);
}, 1000);
}
I'm not exactly sure what it is I'm doing incorrectly. Thanks for the help!

A function object can't draw images to an image from a canvas

The title is poorly worded but there's no way to concisely describe the problem. I'm drawing images to the 2D context of a dynamically created canvas. The data of the context is then saved to an image via toDataURL, which is then draw on every frame. The code below is condensed, I will be drawing multiple images to the context, not just one; which is why I'm saving to an image. I will only draw part of the image at once but the image remains constant so I thought this was the best method, if there are alternatives I will happily accept those as answers.
In short: many images drawn on an image. Part of the image draw each frame.
The code below works:
var picture = new Image();
picture.src = "images/tilesheet.png";
var canvas = document.getElementById("background");
var context = canvas.getContext("2d");
function generate(){
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = canvas.width;
ctx.canvas.height = canvas.height;
ctx.fillStyle = "red";
ctx.rect (0, 0, 40, 40);
ctx.fill();
ctx.drawImage(picture,0,0);
image = new Image();
image.src = ctx.canvas.toDataURL("image/png");
}
function draw(){
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(image, 0,0,100,100,0,0,100,100);
}
function play(){
generate();
setInterval(function(){draw();}, 0.0333);
}
window.onload = function(){
if(picture.complete)play();
else picture.onload = play;
}
<canvas id="background"></canvas>
However this doesn't:
window.Game = {};
canvas = document.getElementById("background");
var tilesheet = new Image();
tilesheet.src = "images/tilesheet.png";
(function(){
function Map(){
this.width = 2736;
this.height = 2736;
this.image = null;
}
Map.prototype.generate = function(){
var ctx = document.createElement("canvas").getContext("2d");
ctx.canvas.width = this.width;
ctx.canvas.height = this.height;
ctx.fillStyle = "red";
ctx.rect (0, 0, 40, 40);
ctx.fill();
ctx.drawImage(tilesheet,0,0);
this.image = new Image();
this.image.setAttribute('crossOrigin', 'anonymous');
this.image.src = ctx.canvas.toDataURL("image/png");
}
Map.prototype.draw = function(context){
context.drawImage(this.image, 0,0, context.canvas.height, context.canvas.height, 0, 0, context.canvas.height, context.canvas.height);
}
Game.Map = Map;
})();
(function(){
var room = new Game.Map();
room.generate();
var draw = function(){
canvas.getContext("2d").clearRect(0, 0, canvas.width, canvas.height);
room.draw(canvas.getContext("2d"));
}
Game.play = function(){setInterval(function(){draw();}, 0.0333);}
})();
window.onload = function(){
if(tilesheet.complete)Game.play();
else tilesheet.onload = Game.play;
}
<canvas id="background"></canvas>
It seems therefore, that the problem is lying in the fact that I'm using function objects but I'm not sure. What am I doing wrong? There are no errors in the debug console.
Those two have different execution order.
First one:
...
Attach image.onload
Call generate()
...
Second one:
...
Call generate()
Attach image.onload
...
That's why it's not working - generate() expects image to be loaded, however second case order doesn't guarantees it.
Instead of
...
room.generate();
...
Game.play = function(){setInterval(function(){draw();}, 0.0333);}
do this
...
Game.play = function(){
room.generate();
setInterval(function(){draw();}, 0.0333);
}

Can't use canvas method putImageData

I have following code:
var img = new Image();
canvas = document.getElementById("c");
ctx = canvas.getContext('2d')
canvas2 = document.getElementById("c2");
ctx2 = canvas2.getContext('2d')
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0);
};
img.src = 'mwq.gif';
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx2.putImageData(imageData, 0, 0);
and i get image on first canvas element, when i check in console there is imageData, with width, lenght and pixel array, but somehow i can't get that image on another canvas element. I dont think there are typos, i rewrote same code several times, and at the end i stripped it to most minimal version without pixel manipulation, but it's still not working.
Your code isn't called in the onload callback, it's executed before the image is loaded so there is nothing to put.
You could change it to
var img = new Image();
canvas = document.getElementById("c");
ctx = canvas.getContext('2d')
canvas2 = document.getElementById("c2");
ctx2 = canvas2.getContext('2d')
img.onload = function () {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img,0,0);
var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
ctx2.putImageData(imageData, 0, 0);
};
img.src = 'mwq.gif';

Categories