I am building a client side map-projection transmuter. I must ask the client to select an image, create an image object, get its size, resize a canvas and paint the image on the canvas. I am stuck on step one.
A priority in this project is legibility so it can be improved by other archivists. I am forbidden from using recursion, self-reference, functions that are called during creation, variable names that are identical to classes of ANY kind, and arrow functions.
This ought to work. It does not. There is no usable feedback at the console.
function imagetocanvas(element) {
let file = element.files[0];
let reader = new FileReader();
reader.onloadend = function() {
const bob = reader.result;
var inmap = new Image();
inmap.src = bob;
alert(bob.width); // UNDEFINED?...WHY??
}
reader.readAsDataURL(file);
}
<input type="file" accept="image/*" id="inputtag" onchange="imagetocanvas(inputtag)" >
<canvas id="primary" width="" height="" >
I believe the following fits into your restrictive criteria. It addresses both concerns that were raised in the comments; neither of which contradicts the other.
Image to load before attempting to access its width.URL.createObjectURL instead of a FileReader if all you're doing is showing the file. See How to work with the url of a fileReader object?I've even added the rendering of the image to the canvas. See How to add image to canvas for more about that process.
const fileInput = document.getElementById('inputtag');
const currentImage = new Image();
const primaryCanvas = document.getElementById('primary');
const context = primaryCanvas.getContext('2d');
// Handle changes to the selected file.
fileInput.addEventListener('change', function (changeEvent) {
// Guard against invalid input (no files).
if (!changeEvent?.target?.files?.length) return;
// Read the file as a blob.
const firstFile = changeEvent.target.files[0];
const fileUrl = URL.createObjectURL(firstFile);
// Update the image.
currentImage.src = fileUrl;
});
// Wait for the image to load before accessing its
// current width or drawing it to the canvas.
currentImage.addEventListener('load', function () {
console.log(currentImage.width);
context.drawImage(currentImage, 0, 0);
});
<input type="file" accept="image/*" id="inputtag">
<canvas id="primary" width="" height="">
I did use optional chaining (?.) to check that the files array existed and had at least one item in it. If you're not allowed to use it, an equivalent check would be:
// Guard against invalid input (no files).
if (!changeEvent
|| !changeEvent.target
|| !changeEvent.target.files
|| !changeEvent.target.files.length) {
return;
}
The check against length serves to check for undefined, null, and length == 0 because all are falsy. This is not a JS-specific concept, but may be unfamiliar depending on the language features you're used to.
For reference, here is the Blob documentation and the URL.createObjectURL documentation which together cover how files are read into memory and accessed.