How to wait until onload event completes its work in JavaScript? - javascript

I'm developing a printing tool using HTML5 canvas. As a test, I've tried to draw an image and a rectangle on the canvas, and then copy it to a new window for printing, using the code below. But all I'm getting in the new window is a blank page.
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<canvas id="pageCanvas"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("pageCanvas");
canvas.height="700";
canvas.width="1000";
var ctx = canvas.getContext("2d");
var imageData="data:image/png;base64,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";
var imageObj = new Image();
imageObj.src = imageData;
imageObj.addEventListener("load", function() {
ctx.drawImage(imageObj, 50, 100,1000,600);
ctx.beginPath();
ctx.rect(100, 101, 200, 100);
ctx.lineWidth = 7;
ctx.strokeStyle = 'black';
ctx.stroke();
}, false);
var printWindow = window.open('');
printWindow.document.write('<html><BODY>');
printWindow.document.write('<center>');
printWindow.document.write('<img src="' + canvas.toDataURL()+'"/>');
printWindow.document.write('</center></body></html>');
printWindow.document.close();
printWindow.print();
</script>
</body>
</html>
Can you please guide me to overcome this issue?

You're opening the new window and trying to copy the content of the canvas onto it immediately after attaching the load event handler to the image, before the handler has actually had a chance to execute.
Just move all the JS code starting with the var printWindow = window.open(''); line inside the event handler, and it should work.
Oh, and please indent your code, especially if you expect anyone else to read it.
Addendum: If you want to wait until multiple images have loaded, the simplest way is to count the load events and call a function when all of them have fired, like this:
var imageURLs = [ ... image URLs here ... ];
var imageObjs = [];
var imagesLoaded = 0;
for (var i = 0; i < imageURLs.length; i++) {
var image = new Image();
image.addEventListener( "load", function() {
imagesLoaded++;
if (imagesLoaded == imageURLs.length) allImagesLoaded();
} );
image.src = imageURLs[i];
imageObjs.push(image);
}
function allImagesLoaded() {
// now do something with imageObjs
};
You could also get fancy and play with things like ES6 promises, but ultimately, the end result is the same.
See also:
Can I sync up multiple image onload calls?
Javascript - wait images to be loaded

Related

How do i do to make wait the program untile an image is load ? (java script)

I have recently started to learn html and i'm currently working on java script. My problem is that i would to stop the program until a image as been load for, after that draw the image on a canvas (because if the image is not load and i want to draw it on a canvas, nothing would be display).
Here's my code (put in one file) :
<html>
<head>
<title>dog food</title>
<link rel = "icon" href = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQudx87gpctKJdgDyq5DpVlb12fI3_7XgbfXw&usqp=CAU">
<style>
canvas.GameWindow {
display : block;
margin-left : auto;
margin-right : auto;
}
</style>
</head>
<body>
<canvas width = 600 height = 350 class = GameWindow>Sorry but the canvas is not taken by your web browser</canvas>
<script>
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
//initialize canvas
/*ctx.fillStyle = 'black';
ctx.fillRect(0, 0, 600, 350);*/
//create function
function drawAnImage(positionX,positionY,width,height,image) {
ctx.drawImage(image, positionX, positionY, width, height);
console.log("an image has been drawn");
};
var img = new Image();
img.src = "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQudx87gpctKJdgDyq5DpVlb12fI3_7XgbfXw&usqp=CAU";
img.onload = function() {
console.log("image load");
};
drawAnImage(0,0,100,100,img);
</script>
</body>
</html>
Actually when i run the code, nothing is display on the canvas because the image is load after i call the drawAnImage function.
Wait for it to load with a callback:
img.onload = function () {
drawImage(0, 0, 100, 100, img);
};
You can also do something if there was an error loading it:
img.onerror = function () {
alert("Oh no an error!");
};
Here it is with ES6 arrow functions and addEventListener:
img.addEventListener("load", () => {
drawImage(0, 0, 100, 100, img);
});
img.addEventListener("error", () => {
alert("Oh no an error!");
});
So i finaly use this little algorithm for image loading :
const imageToLoad = [];
var totalImage = imageToLoad.length;
let imageLoad = [];
for (var i = 0;i<totalImage;i++) {
var img = new Image();
img.src = imageToLoad[i];
imageLoad.push(img);
img.onload = function() {
if (i == totalImage) {
//here i start my game loop
gameLoop(imageLoad);
};
};
};
So what values is for? The first valu imageToLoad is where you would put the images you want to use and imageLoad is where you would find your loaded images. Finaly, for the peoples interested in the algorithm, the algorithm would every time an image is load see if it the last image to load, if yes, the algorithm would start in my case the gameloop of the game.

Javascript function from a JS file doesn't get called from the canvas

I'm trying to learn about JavaScript and the html5 canvas, however, it's proving a little confusing and I don't understand why it doesn't seem to work...
I am working on creating a simple map that has some of the capabilities of google maps(drag and drop/zoom in/out/etc). In order to do this, I chose html5 canvas and easeljs for the drag and drop functions.
I have a javascript file (path.js) which contains 2 functions:
pathConstructor() - example function from the easeljs tutorial
drawMap() - copy of the first function slightly modified (and probably wrong right now)
Everything worked fine when I called pathConstructor() from the canvas, however, after I replaced it with drawMap(), everything stopped working. It won't even work if I replace drawMap() with pathContrcutor() right now.
I put some alerts before and after calling the function from the canvas and inside pathConstructor(). The before alert goes off but the others don't so for some reason the function never gets called...
If I use the pathConstructor code as inline code in the canvas then it works just fine, however, I would like to avoid that since I believe it's bad programming. I want it to be neat and each script to have its own file.
Anyone know why this is happening?
HTML
<!Doctype html>
<html>
<head>
<script src="http://code.createjs.com/easeljs-0.7.0.min.js"></script>
<script src="path.js" type="text/javascript"></script>
</head>
<body>
<canvas id="canvas" width="1300px" height="800px"style="border:1px dotted black;">
<script>pathConstructor();</script>
</canvas>
</body>
</html>
Javascript
var stage;
function pathConstructor() {
alert('inside pathConstructor');
stage = new createjs.Stage('canvas');
// this lets our drag continue to track the mouse even when it leaves the canvas:
// play with commenting this out to see the difference.
stage.mouseMoveOutside = true;
var circle = new createjs.Shape();
circle.graphics.beginFill("red").drawCircle(0, 0, 50);
var label = new createjs.Text("drag me", "bold 14px Arial", "#FFFFFF");
label.textAlign = "center";
label.y = -7;
var dragger = new createjs.Container();
dragger.x = dragger.y = 100;
dragger.addChild(circle, label);
stage.addChild(dragger);
dragger.on("pressmove", function(evt) {
// currentTarget will be the container that the event listener was added to:
evt.currentTarget.x = evt.stageX;
evt.currentTarget.y = evt.stageY;
// make sure to redraw the stage to show the change:
stage.update();
});
stage.update();
}
function drawMap() {
stage = new createjs.Stage('canvas');
var bitMap = new createjs.Bitmap('middle-earth-map.jpg');
stage.mouseMoveOutside = true;
var dragger = new createjs.Container();
dragger.x = dragger.y = 0;
dragger.addChild(bitMap);
stage.addChild(dragger);
dragger.on('pressmove', function(evt2)) {
evt2.currentTarget.x = evt2.stageX;
evt2.currentTarget.y = evt2.stageY;
stage.update();
});
stage.update();
}
For me it's working fine, you just have to remove that extra ")" in dragger.on('pressmove', function(evt2)) {;
dragger.on('pressmove', function(evt2)) {
evt2.currentTarget.x = evt2.stageX;
evt2.currentTarget.y = evt2.stageY;
stage.update();
});

Upload multiple canvas images through javascript loop

I am trying to make an upload script which resizes multiple images client side before the saveimage.php handles them. The reason for this is because they will be uploaded at an outside location where there might be very slow internet.
I have been able to find pieces of code around here which helped me put it together. I am only a beginner so it's probably very messy!
What it currently does is it checks whenever files are being input in the 'file_input' field. Then it looks at the amount of files and loop through them until every file has been placed in the canvas and upload while it's in there.
However, the problem is: when I don't add an alert for each file, the loop goes too fast and only processes 1 or 2 out of 10 images for example. Because the upload script will go faster than the canvas can be updated with a new image.
This is my current page, simplified to the core:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
</head>
<body>
<form>
<input id="file_input" type='file' multiple />
</form>
<div id="preview">
<canvas id="canvas"></canvas>
</div>
<script>
var input = document.getElementById('file_input');
input.addEventListener('change', handleFiles);
function handleFiles(e) {
var files = input.files;
alert(files.length +" files are being uploaded!"); // display amount of files for testing purpose
for (var i = 0; i < files.length; ++i) {
alert("Upload file number: "+i); // display file # for testing purpose, when this is removed the script will go too fast
var MAX_HEIGHT = 1000;
var ctx = document.getElementById('canvas').getContext('2d');
var img = new Image;
img.onload = function(){
if(img.height > MAX_HEIGHT) {
img.width *= MAX_HEIGHT / img.height;
img.height = MAX_HEIGHT;
}
var ctx = canvas.getContext("2d");
ctx.clearRect(0, 0, canvas.width, canvas.height);
preview.style.width = img.width + "px";
preview.style.height = img.height + "px";
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0, img.width, img.height);
// the canvas should contain an image now and this will send it through saveimage.php
var myDrawing = document.getElementById("canvas");
var drawingString = myDrawing.toDataURL("image/jpeg", 0.5);
var postData = "canvasData="+drawingString;
var ajax = new XMLHttpRequest();
ajax.open("POST",'saveimage.php',true);
ajax.setRequestHeader('Content-Type', 'canvas/upload');
ajax.onreadystatechange=function()
{
if (ajax.readyState == 4);
}
ajax.send(postData);
};
img.src = URL.createObjectURL(e.target.files[i]);
}
}
</script>
</body>
</html>
And this is my saveimage.php which works well, but just for the complete overview:
<?php
if (isset($GLOBALS["HTTP_RAW_POST_DATA"]))
{
$rawImage=$GLOBALS['HTTP_RAW_POST_DATA'];
$removeHeaders=substr($rawImage, strpos($rawImage, ",")+1);
$decode=base64_decode($removeHeaders);
// check if the file already exists and keep adding +1 intil it's unique
$i = 1;
while(file_exists('uploads/image'.$i.'.jpg')) {
$i++;
}
$fopen = fopen( 'uploads/image'.$i.'.jpg', 'wb' );
fwrite( $fopen, $decode);
fclose( $fopen );
}
?>
A bit of extra information:
I have added canvas, because as far as I can understand that's the
only way to resize images client side. In the final script it will be
set to hidden.
If the canvas could be skipped and the data sent to saveimage.php
immediately then that would solve the problem too I think.
As I said I am not very experienced with javascript, so if there is a
much simpler way to achieve this goal. Please let me know!
Thanks in advance!
JavaScript loads image asynchronously. That means once it is assigned a new image's .src it will begin loading the image but will simultaneously continue processing the javascript after the .src while the image takes time to load.
You're using the same image variable (var img) inside your for loop. Therefore, each time through the loop you are overwriting the previous img before the previous image has been fully loaded.
Here's an image loader that fully loads all image and then calls the start() function where you can do you processing:
// image loader
// put the paths to your images in imageURLs[]
var imageURLs=[];
imageURLs.push("myImage1.png");
imageURLs.push("myImage2.png");
// etc, etc.
// the loaded images will be placed in imgs[]
var imgs=[];
var imagesOK=0;
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// the imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
}
In the onload callback use the this keyword(instead of img) to for the current image, img may/will be overwritten in the for loop before the callback fires.
img.height --> this.height etc
Also is there a reason you're using a custom content type instead of application/x-www-form-urlencoded ?
Url encoded form data is much easier to work with.
I have struggled with the same problem for some time now, but I finally
cobbled together another solution, using bits of code from others, who have addressed this problem,
and it works. It may not be perfect, and I would welcome any improvement suggestions.
The concept is that you have two Javascript
Functions, which are identicle called Resize0 and Resize1, and they call each other
until all photos have been resized then the Function which resizes the
last image Submits the Form. The two Functions pass parameters between
each other so that one of them will know when to Submit the Form.
Two of those parameters are, Number_Of_Images and current Image_Number.
You can also download a working Example Web page from
http://www.wantitconsulting.co.nz/ExampleResizeUpload.zip .
You will need to create a folder in the base directory of your test web site
for the Images to go into. The foldername is TestResizeUpload. The Server
side uses php.

Canvas image not displaying until second attempt

I'm trying to use the element to draw a static Google Maps image that comes onscreen once a user clicks on a submit button. The html looks like this:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=MYKEY&sensor=true">
</script>
<script type="text/javascript" src="createmap.js">
</script>
</head>
<body>
<form onsubmit="display_map(34.1,-76.08168); return false;">
<input type="submit" value="Submit"/>
</form>
<canvas id='map-canvas' />
</body>
</html>
And the display_map() function in createmap.js:
function display_map(center0, center1) {
var image = new Image();
image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
+ center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
var canvas = document.getElementById('map-canvas');
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
}
The first time that the user clicks on the submit button, nothing happens. Every subsequent click, however, will load the image (even if the tab is closed and then reopened). Changing the center0 and center1 arguments will reset the page and again force two clicks to display the new image that Google generates. This behavior doesn't seem to be coming from Google Maps, as the same issue occurs when I load an image from my hard drive. This is happening in every browser I've tested (Firefox, IE and Chrome).
It's because the first time the image hasn't loaded properly so the canvas doesn't draw anything. The image loads asynchronous in the background so your function will continue regardless.
To handle this scenario try with:
function display_map(center0, center1) {
var image = new Image();
image.onload = function() {
var canvas = document.getElementById('map-canvas');
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
}
image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
+ center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
}
That the function returns immediately is something that needs to be taken into account in case you do several draw operations to canvas (graphics on top for instance).
For these cases you need to use callbacks so when an image has finished loading you call the next step from within the onload handler with a single extra parameter:
function display_map(center0, center1, callback) {
var image = new Image();
image.onload = function() {
var canvas = document.getElementById('map-canvas');
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
callback();
}
image.src = 'http://maps.googleapis.com/maps/api/staticmap?center='
+ center0 + ',' + center1 + '&zoom=13&size=800x800&sensor=false';
}
Now you can create a call chain:
function step1() {
display_map(center0, center1, step2);
}
function step2() {
/// called when step1 has finished
}

javaScript multiple time image not loading

I am drawing image which is loaded using loader method in two different places. But it only displays the second one. (I am following this http://www.html5canvastutorials.com/tutorials/html5-canvas-image-loader/)
If I add an alert() it works in Fx but not in Chrome. I want it to work everywhere without alert()
If I try drawing Image without using preloaded image I am getting the desired result. But I am thinking it is extra load (http://www.html5canvastutorials.com/tutorials/html5-canvas-images/)
ImageOnload("O",120,120); //This image not displaying
alert("If i add alert it works only in Fx but not in Chrome")
ImageOnload("O",120,20);//only this is displaying ???
<html>
<head>
</head>
<script type="text/javascript" >
var ctx;
var ImageVariable={};
window.onload= function()
{
var canvas = document.getElementById("gameLoop");
ctx = canvas.getContext("2d");
ImageBuilder(ImageSourceDB);
ImageOnload("O",120,120); //This image is not displaying
//alert("If i add alert it works only in FFox but not in chrome")
ImageOnload("O",120,20);
}
var ImageSourceDB=
{
X:"./Images/X.gif",
O:"./Images/O.gif"
}
function ImageBuilder(ImageSrcDB)
{
for (iSrc in ImageSrcDB)
{
ImageVariable[iSrc]= new Image();
ImageVariable[iSrc].src = ImageSrcDB[iSrc];
}
}
function ImageOnload(ImageSrc,x,y)
{
ImageVariable[ImageSrc].onload= function ()
{
ctx.drawImage(ImageVariable[ImageSrc],x,y);
};
ImageVariable[ImageSrc].src = ImageSourceDB[ImageSrc];
}
</script>
<body>
<canvas class ="pattern" id="gameLoop" height="300" width="300" />
</body>
</html>
List item
ImageOnload("O",120,120); //This image not displaying
ImageOnload("O",120,20);//only this is displaying ???
You forgot to change the id of the object:
ImageOnload("O",120,120);
ImageOnload("X",120,20); // Use "X", not "O"!!!
If you still want to show "O" twice, then you should draw it twice, but with only one onload function. See example below:
<script type="text/javascript" >
var ctx;
var ImageVariable={};
var ImageSourceDB = {
X:"./Images/X.gif",
O:"./Images/O.gif"
}
window.onload = function() {
var canvas = document.getElementById("gameLoop");
ctx = canvas.getContext("2d");
ImageBuilder(ImageSourceDB);
ImageVariable["O"].onload = function() {
// this will be executed when the image "O" is loaded
// this is a pointer to ImageVariable["O"]
ctx.drawImage(this, 120, 120);
ctx.drawImage(this, 120, 20);
}
ImageVariable["X"].onload = function() {
// this will be executed when the image "X" is loaded
ctx.drawImage(this, 30, 30);
}
}
function ImageBuilder(ImageSrcDB) {
for (iSrc in ImageSrcDB) {
ImageVariable[iSrc]= new Image();
ImageVariable[iSrc].src = ImageSrcDB[iSrc];
}
}
</script>

Categories