Canvas 使用 drawImage 初次加载不显示图片

528 阅读1分钟

CanvasdrawImage 使用记录

项目背景

最近在项目中遇到一个bug,记录下解决方案。该项目使用canvas的绘制功能,在画布中绘制各种图形以及图片等。其中图片资源的绘制使用的是CanvasDrawImage:

interface CanvasDrawImage {
    /** [MDN Reference](https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/drawImage) */
    drawImage(image: CanvasImageSource, dx: number, dy: number): void;
    drawImage(image: CanvasImageSource, dx: number, dy: number, dw: number, dh: number): void;
    drawImage(image: CanvasImageSource, sx: number, sy: number, sw: number, sh: number, dx: number, dy: number, dw: number, dh: number): void;
}

例如,通过下面的方式绘制svg图标

        ctx.drawImage(
          Graphics.getImageSource(svg)!,
          rect.left,
          rect.top,
          15,
          15,
        );

其中 ctxOffscreenCanvasRenderingContext2D 类型。

问题现象

  • 将绘制的文件(包含image)导出到本地磁盘,再次加载保存的文件,在canvas初次渲染的时候,图标未显示出来;

解决方案

  • img.onload() 回调方法中执行绘制操作,即:
    svgImg.onload = function () {
        ctx.drawImage(svgImg, imgX, imgY, imgWidth, imgHeight);
      };

以上方案解决了图片初次加载不显示的问题,但鼠标选中包含图标资源的元素时,图标会出现模糊闪动的现象。优化方案如下:

  • 使用 img.complete 来判断图片是否已加载完成,如果加载完成,则无需在加载回调中执行绘制操作,即:
    if (svgImg.complete) { // 如果图片已经存在于浏览器缓存,直接调用回调函数  
      ctx.drawImage(svgImg, imgX, imgY, imgWidth, imgHeight);
    } else {
      svgImg.onload = function () {
        ctx.drawImage(svgImg, imgX, imgY, imgWidth, imgHeight);
      };