asleniovas
asleniovas

Reputation: 333

img.onload refuses to fire after new Image() declaration

I'm trying to load an image on to a canvas so I can write some text on it and maybe save it later on. I have two below functions:

openImage = (memeURL, index) => {

    this.setState({currentMeme: index}, () => {

        const base_image = new Image();

        base_image.crossOrigin = "anonymous";
        base_image.src = memeURL;

        const base64 = this.getBase64Image(base_image);

        this.setState({currentImagebase64: base64});
    })


}

getBase64Image(img) {

    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    var dataURL = canvas.toDataURL("image/png");
    return dataURL;
}

The openImage function is bound to an onClick event so when I click an image it fires up the above operations so that my <img src=""> can feed from state and display the image.

The problem is that when i click the image it never shows up and my currentImagebase64 state value is always data; BUT if debug with web tools it appears fine because theres enough time for the image to load. Aparrently the solution is in the below answer:

canvas.toDataUrl() returns 'data:,'

However, if I write something like suggested the onload function never triggers. For example below code won't trigger the onload for some reason, it just stops executing when it reaches it:

openImage = (memeURL, index) => {

    this.setState({currentMeme: index}, () => {

        const base_image = new Image();

        base_image.onload = function() {

            this.crossOrigin = "anonymous";

        }

        //Set src AFTER the image has loaded
        base_image.src = memeURL;

        const base64 = this.getBase64Image(base_image);

        this.setState({currentImagebase64: base64});
    })


}

Can any subject experts lend a hand please?

Upvotes: 1

Views: 1982

Answers (2)

Jaromanda X
Jaromanda X

Reputation: 1

const base64 = this.getBase64Image(base_image);
this.setState({currentImagebase64: base64});

needs to be executed once the image has loaded

and

base_image.crossOrigin = "anonymous";

needs to be done before setting the src

So, the code becomes

openImage = (memeURL, index) => {
    this.setState({currentMeme: index}, () => {
        const base_image = new Image();
        base_image.crossOrigin = "anonymous";
        base_image.onload = () => { // use arrow function so `this` will be what is needed
            const base64 = this.getBase64Image(base_image);
            this.setState({currentImagebase64: base64});
        }
        base_image.src = memeURL;
    })
}

Your comment

//Set src AFTER the image has loaded

suggests you don't know how onload works ... you set src which starts loading the image, and then onload is triggered when image finishes loading

Upvotes: 1

Gavin
Gavin

Reputation: 2365

I'm not entirely sure how react handles the states as above but I've had a similar issue in vanilla JS in which the src wasn't loading until added to the DOM. Keeping it hidden was fine though:

const image = new Image();
image.onload = (e)=>{
    // do something
}
image.src = YOUR_IMAGE_PATH;
image.hidden = true;

// add to body
document.body.appendChild(image); // at this point the src is loaded and onload handler is fired

Upvotes: 0

Related Questions