Reputation: 388
I'm having a problem with the canvas not drawing all images (only some are drawn) on specific devices.
To be exact Mobile Chrome (Samsung), I have not met this issue on any other device so far.
const drawSymbol = (
ctx: CanvasRenderingContext2D,
symbol: CardSymbol,
image: HTMLImageElement,
) => {
window.requestAnimationFrame(() => {
ctx.drawImage(
image,
symbol.x,
symbol.y,
symbol.width,
symbol.height,
);
});
};
useEffect(() => {
const canvas = canvasRef.current;
if (canvas) {
const ctx = canvas.getContext('2d');
if (ctx) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (const symbol of card) {
const image = images[symbol.image.id];
if (image.loadedImg) {
drawSymbol(ctx, symbol, image.loadedImg);
} else {
const img = new Image();
img.onload = () => {
image.loadedImg = img; // Cache loaded image
drawSymbol(ctx, symbol, img);
};
img.src = image.src;
}
}
}
}
}, [card]);
Some images seem to draw and some simply don't. I've noticed that sometimes a portion of the images draw and then get removed and a different portion is drawn, but I cannot confirm if this actually happens as it's hard to spot (milliseconds). Does anyone have an idea why could this be happening?
Do you think that a single window.requestAnimationFrame
for all images could solve the issue?
Upvotes: 1
Views: 83
Reputation: 388
Ok, I managed to fix it by gathering all the images first and then drawing the images with only one requestAnimationFrame
.
const getHtmlImage = async (imageId: number) => {
const image = images[imageId];
if (image.loadedImg) {
return image.loadedImg;
} else {
return new Promise<HTMLImageElement>((resolve) => {
const img = new Image();
img.onload = () => {
image.loadedImg = img; // Cache loaded image
resolve(img);
};
img.src = image.src;
});
}
};
...
const htmlImagesPromises = card.map((symbol) =>
getHtmlImage(symbol.image.id),
);
const htmlImages = await Promise.all(htmlImagesPromises);
window.requestAnimationFrame(() => {
...
});
Upvotes: 0