Search code examples
javascripthtml5-canvasblazorblazor-hybrid

Drawing picture on html canvas with JSInterop from Blazor


I'm using the html canvas from inside Blazor hybrid using JSInterop.

So far it was working fine, but now I need to add a picture on the canvas and it is not working.

I have placed the picture in the wwwroot/Images/Image2.jpg folder. In the JS file I have:

let canvasCtx;
const image = new Image();
image.src = 'Images/Image2.jpg';

function InitBgndImage1(chart) {
canvasCtx = chart.getContext("2d");

//canvasCtx.beginPath();
//canvasCtx.rect(20, 20, 150, 100);
//canvasCtx.stroke();
canvasCtx.drawImage(image, 0, 0);}

The function is called from the Blazor file as follows:

<div class="chart-container">
<canvas @ref="chartCanvas"></canvas>

@code { ElementReference chartCanvas;

protected override void OnAfterRender(bool firstRender)
{
    base.OnAfterRender(firstRender);
    JS.InvokeVoidAsync("InitBgndImage1", chartCanvas);
}

}

The rectangle is drawn when not commented but the picture never displays.

What could be the reason?


Solution

  • This is not due to Blazor but due to Javascript.

    When you set image.src = 'Images/Image2.jpg';, the image is not actually loaded yet. You have to wait for it to load before drawing.

    Try this:

    document.querySelector("button").addEventListener("click", async () => {
      const img = new Image();
      
      await new Promise(r => {
        img.onload = r;
        img.src = "https://fastly.picsum.photos/id/237/200/300.jpg?hmac=TmmQSbShHz9CdQm0NkEjx1Dyh_Y984R9LpNrpvH2D_U";
      });
      
      const canvas = document.querySelector("canvas");
      const ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0);
    });
    <p>
      <button>Draw</button>
    </p>
    
    <canvas></canvas>

    If you didn't wait, you can see it doesn't work as well (a cache may make it work the 2nd attempt):

    document.querySelector("button").addEventListener("click", () => {
      const img = new Image();  
      img.src = "https://fastly.picsum.photos/id/237/200/300.jpg?hmac=TmmQSbShHz9CdQm0NkEjx1Dyh_Y984R9LpNrpvH2D_U";
      
      const canvas = document.querySelector("canvas");
      const ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0);
    });
    <p>
      <button>Draw</button>
    </p>
    
    <canvas></canvas>