CanvasTexture doesn't show loaded images on mesh

Its an async problem, basically the CanvasTexture is generated before the image get loaded and drawn, you can solve this by using a Promise and await for the image to be loaded and drawn.

Or you can move this line const bodyTexture = new THREE.CanvasTexture(canvas); up, and set the texture texture.needsUpdate = true at the onLoaded callback :

const canvas = document.getElementById("canvas");
const bodyTexture = new THREE.CanvasTexture(canvas);
if (canvas.getContext) {
    ...
    img.onload = function () {
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        bodyTexture.needsUpdate = true;
    };
    ...
}