Question

I'm having an issue with getting the dimensions of a newly updated image element.

I'm using FileReader to display a preview of an image file on screen. Once the filereader and associated code has finished executing, I retrieve the new dimensions of the image element so I can adjust them accordingly.

On some browsers, the info doesn't get updated straight away and I need to include a delay before I can retrieve the new dimensions. This results in the new image being resized according to the previous image's dimensions, and not its own.

How can I be sure the new image has been fully loaded?

I would have thought FileReader().onloadend would have been sufficient but apparently not. I think this is executed once the fileReader has loaded it, not when the DOM has rendered it. (Am I right?)

Then I found this question, which suggests using a timeout of 1 millisecond. This works sometimes, but not always. It seems to be down to the speed the browser is rendering the image (more-so available resources rather than filesize). Do we have no other way of detecting a change in these parameters?

HTML

<img src="#.png" alt=""/>
<input id="fileInput" type="file" accept='image/*' onChange="loadIt()" />

JS

preview = getElementsByTagName('img')[0];

function loadIt() {

    var imgReader = new FileReader();
    imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input

    imgReader.onloadstart = function(e) {
        //
    }
    imgReader.onload = function (imgReaderEvent) {
        if (isImage()) {
            preview.src = imgReaderEvent.target.result;
            //
        }
        else {
            preview.src = 'error.png';
            //
        }
    }
    imgReader.onloadend = function(e) {

        setImage();

        setTimeout(function(){
            setImage();
        }, 1);

        setTimeout(function(){
            setImage();
        }, 2000);
        //
    }
};

function setImage() {
    preview_w = preview.width;
    preview_h = preview.height;
    console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
    //
};
Was it helpful?

Solution

You should call preview.onload or preview.onloadend on your image to detect that it has finished loading. You're also calling your events after you readAsDataURL The code should look like this

var preview=document.getElementsByTagName("img")[0];
function loadIt() {
   var imgReader=new FileReader();
   imgReader.onload=function(){
   if (isImage()) {
      preview.src = imgReader.result;
      preview.onload=setImage;
   } else {
      preview.src = 'error.png';
      //
   }
   imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input
}
function setImage(){
   preview_w = preview.width;
   preview_h = preview.height;
   console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
}

OTHER TIPS

You're calling imgReader.readAsDataURL before your .onload and .onloadend is set.

I do not know what some of the variables are with-in the body of your setImage();however, start here:

function loadIt() {

    var preview = getElementsByTagName('img')[0],

        setImage = function () {
        preview_w = preview.width;
        preview_h = preview.height;
        console.log('dimensions: '+avatar_preview_w+' x '+avatar_preview_h);
    },

    imgReader = new FileReader();

    imgReader.onloadstart = function(e) {};

    imgReader.onload = function (imgReaderEvent) {
        if (isImage()) {
            preview.src = imgReaderEvent.target.result;
        }
        else {
            preview.src = 'error.png';
        };
    };

    imgReader.onloadend = function(e) {setImage();};

    imgReader.readAsDataURL(document.getElementById('fileInput').files[0]); //read from file input
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top