I'm working on a React component that receives an imageUrl and visualizes it on a canvas. The component intentionally adds a 2-second delay to simulate loading time for large images. However, I'm facing an issue: when the imageUrl changes in the parent component and while the image is loading, the previous image disappears from the browser momentarily then the new image is shown, causing a flicker effect. The behavior I am looking for is the component keeps showing the previous image until the new image is fully loaded and the swaps them.
How can I modify my existing code to ensure that the transition between images is smooth without any flicker? Here's my current implementation:
class ImageViewer extends React.Component {
constructor(props) {
super(props);
this.imagecanvas = React.createRef();
}
componentDidMount() {
this.drawCanvas();
}
componentDidUpdate(prevProps) {
if (prevProps.imageUrl !== this.props.imageUrl) {
this.drawCanvas();
}
}
drawCanvas() {
const canvas = this.imagecanvas.current;
const context = canvas.getContext('2d');
const image = new Image();
// Clearing previous image
context.clearRect(0, 0, canvas.width, canvas.height);
// Load new image
image.onload = () => {
setTimeout(() => {
context.drawImage(image, 0, 0);
}, 2000);
};
image.src = this.props.imageUrl;
}
render() {
return (
<canvas id="imageView" ref={this.imagecanvas}></canvas>
);
}
}
Any suggestions or improvements to prevent the flicker during image loading would be greatly appreciated!
I have searched the internet and found the structure provided above is very common, however, I have not seen any mention of the flickering issue and how to address it.
IMO, keeping the previous image and display the new one when it's fully loaded is not a good UX because user will see the image is there but in couple of seconds it is replaced by another one and user get confused.
To handle flickering when image is loading, we have couple of solution
But the idea behind all these technique are the same. We need a kind of placeholder with the same size with the image being loaded to prevent flickering. In case of skeleton loading, it is just a placeholder with loading effect.
In The second case, instead of a loading effect, We use a blurry version of your image (which is loaded very fast) to place there first, and when your high resolution image is fully loaded, replace with the blurry one.
You could base on the code below to figure out how it works on your own code.