Reputation: 165
I have tried adding an eventListener to draw the image only after the image has loaded. I have also tried placing the event listener before and after setting the image src but still nothing seems to work.
I just cant seem to figure out exactly what's causing this. Can someone explain please.
import React from 'react';
import {useEffect, useState} from 'react';
function Main() {
//initiate state
const [ plane, setPlane ] = useState( new Image() );
const [ star, setStar ] = useState( new Image() );
const [ bird, setBird ] = useState( new Image() );
const [ parachute, setParachute ] = useState( new Image() );
const [ cloud, setCloud ] = useState( new Image() );
//draw the game animation
let draw = () => {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d'); //context
//set background color
context.fillStyle = '#74b9ff';
//context.fillRect(0, 0, canvas.width, canvas.height);
//load images
plane.src = 'images/plane.png';
plane.onload = drawImage( context);
star.src = 'images/star.png';
bird.src = 'images/bird.png';
parachute.src = 'images/parachute.png';
//cloud.src = 'images/cloud.png';
// setPlane( prevState => { return {...prevState, src: 'images/plane.png' } } );
// setStar( prevState => { return {...prevState, src: 'images/star.png' } } );
// setBird( prevState => { return {...prevState, src: 'images/bird.png' } } );
// setParachute( prevState => { return {...prevState, src: 'images/parachute.png' } } );
// setCloud( prevState => { return {...prevState, src: 'images/cloud.png' } } );
}
let drawImage = ( context ) => {
context.drawImage(plane, 0, 0, 50, 50);
}
useEffect( () => draw(), [] );
return (
<div className="container">
<canvas width='400px' height='400px' id='canvas'></canvas>
</div>
);
}
export default Main;
Upvotes: 0
Views: 842
Reputation: 12891
It might not be obvious but your issue is caused by the following line:
plane.onload = drawImage( context);
If written that way, it simply doesn't do what you might think. The onload event can be assigned a callback function - which as the name implies - fires a function as soon as something finished loading. If you append parentheses ()
, it will actually execute the function right away.
That means it will try to draw the image before it even finished loading.
What you need to to is pass a reference to your function by it's name only.
plane.onload = drawImage;
The problem in your case is that you want to pass a parameter. This can't be done - at least not in this way.
What you can do however is making the context a property of the Image object itself.
Something like:
let draw = () => {
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d'); //context
context.fillStyle = '#74b9ff';
plane.context=context;
plane.onload = drawImage;
plane.src = 'images/plane.png';
}
let drawImage = ( e ) => {
e.target.context.drawImage(plane, 0, 0, 50, 50);
}
Upvotes: 1