loop to create multiple canvas with multiple images not always displaying images - javascript

this may be an odd one to explain:
I want to create dynamically a collection of canvas that will have a single image in it. And this displays (after much hassle and getting rid of the onload event) but when I try to refresh the page I sometimees get nothing on the screen.
And when I was using thee onload event (to wait until the image is loaded) it would not display or display everything in the last canvas.
Here is a snippet of the code:
var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
img = new Image()
img.src = sources[i]
canvas = document.createElement('canvas')
$(canvas).attr('id', i)
canvas.height=300
canvas.width=200
var context = canvas.getContext('2d');
//onload commented out allows expected display
//img.onload = function() {
context.drawImage(img, 0, 0);
//}
divCanvas.appendChild(canvas)
}
I have seen many posts that seemed to look like mine and tried quite a few but to no avail.

I think the issue is that var context is overwritten before the img.onload event is triggered. The img.onload event only has a reference to global scope. This is why only the last image shows up. You need to find the correct context inside the event.
I can't test your code directly, but I think it should be something like this:
var sources = []//the array that contains the images
var divCanvas = document.getElementById('showcase-wrapper')
for(var i=0; i<sources.length; i++){
img = new Image();
img.src = sources[i];
img.id = i; //Allow img to remember its corresponding canvas/context
canvas = document.createElement('canvas');
$(canvas).attr('id', i);
canvas.height=300;
canvas.width=200;
var context = canvas.getContext('2d');
divCanvas.appendChild(canvas);
img.onload = function() {
//Use the image id to get the correct context
var canvas = document.getElementById(this.id);
var context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
}
}

For consistent behavior, you must use onload. If you don't the canvas drawing code may execute before the image is loaded and the desired image will not be drawn.
It might be that the onloads that would draw to the other canvases are not being called because the Images are getting garbage collected before the event can fire.
Try adding
var images = [];
At the start of your code and
images.push(img);
After the img = new Image() line.
If that doesn't work, try adding those images to the DOM tree-- img.setAttribute('style', 'display: none') first so you don't see them and they don't interfere with the document structure.

I found the fix here:
https://developer.mozilla.org/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Drawing_images
Apparently they have dropped img.onload to have the function called when the body has finished loaded.
Though, I still do not understand why my script or, ellisbben solution was not working.
If anyone as an answer for it, it would be very welcomed...

Related

Wait for an image class to load in JavaScript

I want my code in JavaScript to pause when I create and image and wait for it to load before continuing. I tried writing this code:
var width, height = "width", "height"
img = new image()
image.onload = () => {width = this.width; height = this.height}
image.src = "https://cdn.discordapp.com/avatars/418893693106389024/aaed638ebdb3bfe2d4e1d3e7f9da62ef.png?size=256"
console.log(width, height)
However, when I run this code width height gets printed to the console. Is there a way to wait for the image to load before anymore code is run? If so, please help. Thanks.
You can use the setTimeout() method and wait the seconds that you need before execute the lines after.
Put anything you need to use the width/height for in the onload so it only runs after the image has loaded:
const image = new Image()
image.onload = function () {
console.log(this.width, this.height)
}
image.src = "https://cdn.discordapp.com/avatars/418893693106389024/aaed638ebdb3bfe2d4e1d3e7f9da62ef.png?size=256"
First of all your code had whole lot of miss matches.
by language convention classes are set with UpperCamel case so Image() not image()
secondly when we are encapsulating code in event listener such as on load we need everything that we need to execute in that encapsulation.
console.log out side of onload function is dealt at global level not sent in memory to execute latter on. So move it into on load function.
var img = new Image();
img.onload = function () {let width = this.width; let height = this.height;
console.log(width, height);}
img.src = "https://cdn.discordapp.com/avatars/418893693106389024/aaed638ebdb3bfe2d4e1d3e7f9da62ef.png?size=256";

Functions, and Image importing

I'm working on a project in game development in Javascript and HTML5 canvas. I have this common code I use for loading sprites:
var sprite = new Image();
sprite.src = "sprite.png";
I was wondering if there was a simpler way to do this, which I first thought by function, but not sure how I should do so. I would think to do so like this:
function loadSprite(src) {
this.src = src;
}
var loadSprite(sprite.png);
However I don't think this is the right way to do it. Could someone correct my code and/or give a simpler way of loading an image like this? (I am also using a ctx.drawImage(..., sprite) in order to change coordinates on the canvas so it needs an x,y,width,and height parameters in one way or another)
Why not use as below:
function loadSprite(src) {
var sprite = new Image();
sprite.src = src;
return sprite
}
var _local_var = loadSprite('sprite.png');

ERROR: Image is not defined (trouble using Image() function)

I use a very simple piece of code (but then obviously with my image instead of Image.png). I am trying to give my canvas a background image.
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img = new Image();
img.onload=start;
img.src="Image.png";
function start(){
ctx.drawImage(img,0,0);
}
But I receive this error:
ERROR: 'Image' is not defined. [no-undef] about the part:
var img = new Image().
I tried to replace this with
var img = document.createElement("img");
Then the error is gone, but nothing displays, no image whatsoever, its just empty.
Has anybody any idea what I am doing wrong?
Thanks in advance!
FULL CODE
var document;
var ctx;
var window;
window.onload = function () {
start();
}
function start(){
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var img = document.createElement("img");
img.src="image.png";
img.onload=start;
function start(){
ctx.drawImage(img,0,0,400,400);
}
}
You need to attach the image you have created to the DOM.
document.getElementById("image-container").appendChild(img);
Edit: I apologize, I see you are drawing it to a canvas object. In that case I would suspect that your image is failing to load properly.
A couple ideas: you could add some debugging output within the start() function or set a breakpoint, then look at what the 'img' contains at that point in time. Or you could check the status code on the 'Network' tab of the devtools console. Or you could replace the image with one that is known to work, such as www.google.com/images/logo.png. This all should hepl you narrow down the issue.
Note: window is a global variable so you shouldn't declare it, and names that are properties of window such as window.document are also globals - can be referenced as document without declaring it. Occasionally JS frameworks complain, but there are framework-specific ways to solve this. Duplicate declaration of these variables is not a good path to go down.
If you're adding these in response to ESlint errors, you should add eslintrc.json to your project root (if you don't have it already), and give it the following property so it doesn't complain for browser globals:
{
"env": {
"browser": true
}
}
As to why Image is not defined, this would not happen on a modern browser environment. It has to be something with your environment setup. Is there any information you could provide about how you are running this code?
Try setting the onload callback before you set the image's src.
var img = document.createElement("img");
img.onload=start;
img.src="image.png";
If the image is cached, then onload would be fired as soon as src is set, i.e. before it is assigned to start see this question.

How can you overlay an image on a canvas, then draw on top of it?

I have all the code worked out to draw on a canvas in a separate .js file, so now I just need to put the image on.
I can’t get the image to work, though, the normal method isn’t working. I’ve tried this:
var canvasvar;
var contextvar;
canvasvar = document.getElementById("canvas");
contextvar = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = "http://wannabevc.files.wordpress.com/2010/09/im-cool.jpg";
contextvar.drawImage(imageObj,10,10);
For one thing, should I put this inside the html file, inside a <script></script> at the end, or should I put it in the js file that has the “draw stuff” code? I can’t get either to work, it runs with no errors but I don’t see any image over the canvas. So I can still draw, but no image appears. I’m guessing the image is under the canvas or something.
I’m guessing this is because I didn’t just make a canvas – I made it with all this programming happening inside it in another js file.
I also tried putting this code inside the initCanvas function in my .js code. This is what actually creates the canvas. Here is the code of initCanvas function:
// Retrieve canvas reference
canvas = document.getElementById("canvas");
// Size canvas
canvas.width = 600;
canvas.height = 400;
// Retrieve context reference, used to execute canvas drawing commands
context = canvas.getContext('2d');
context.lineCap = "round";
// Set control panel defaults
document.getElementById("thickness").selectedIndex = 0;
document.getElementById("color").selectedIndex = 1;
// Overlay image over the canvas. THIS PART IS WHAT I'M ASKING ABOUT. This is usually
// not in the code
var canvasvar;
var contextvar;
canvasvar = document.getElementById("canvas");
contextvar = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = "http://wannabevc.files.wordpress.com/2010/09/im-cool.jpg";
contextvar.drawImage(imageObj,10,10);
So the last part in this code is what I’m talking about. It isn’t working, though.
Give your image time to load using imageObj.onload
var canvasvar = document.getElementById("canvas");
var contextvar = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload=function(){
contextvar.drawImage(imageObj,10,10);
}
imageObj.src = "http://wannabevc.files.wordpress.com/2010/09/im-cool.jpg";

Javascript calculate image size, after image load

function loader(img) {
var imgH = img.height;
var imgW = img.width;
console.log(imgH, imgW);
};
img = new Image();
img.src ='../images/pic1.jpeg';
img.onLoad = loader(img);
So, It is exepeted, that I'll get image's size, but I got "0 0" in console. And size of image is 500X700. What's wrong with this code?
This makes no sense:
img.onLoad = loader(img);
you want to pass the actual function to the event:
img.onload = loader;
and use this instead of img within the function.
Also you need to assign the event before changing the image's src property.
Also note that there are numerous problems with the load event on images. From the jQuery manual on load():
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load() shortcut is to execute a function when an image (or collection of images) have completely loaded. There are several known caveats with this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Try this:
function loader(){
var imgH = this.height;
var imgW = this.width;
console.log(imgH, imgW);
}
var img = new Image();
img.onload = loader;
img.src ='../images/pic1.jpeg';
I used this way:
img.onload = function(){//here wrote everything from loader};
And it was the only working solution I have found.
I found the best way is to let the computer do the scaling first.
and declaring the onload = "some_function()" in the body.
<body onload="some_function()">
and then getting the sizing afterward in the script.
some_function(){
var image1 = document.getElementsByClassName('main')[0];
var computedStyle_image1 = window.getComputedStyle(image1);
var image_width = computedStyle_image1.getPropertyValue('width');
}
I noticed with google chrome you need to make sure you call the onload="function" within the body div otherwise the image values arn't set and it pulls in 0px for width and height.

Categories

Resources