You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中确保图片加载完成后再渲染Canvas的最佳实践

问题:Angular中确保图片加载完成后再渲染Canvas的优雅方案

我熟练掌握TypeScript/JavaScript,正在开发首个Angular应用,其中包含一个带有多个Canvas的大型CAD绘图板组件,图片为程序化加载。

请问有没有简洁、可扩展的方式确保图片加载完成后,再调用ctx.drawImage()进行渲染?这似乎是个已解决的问题,但我找到的方案都像是临时拼凑的。

有人使用Promises,但NgAfterViewInit()并非异步方法。我知道可以将其声明为异步并在加载Promise上调用await,但这看起来不够优雅且容易出错。

或许可以用如下这种传统方案?

class ImagesLoader {
  private readonly images: Map<string, HTMLImageElement>;
  private readonly pendingActions: ((images: Map<string, HTMLImageElement>) => void)[] = [];
  public readonly errors = new Set<string>();
  private remainingCount: number;

  constructor(urls: string[]) {
    this.remainingCount = urls.length;
    this.images = new Map<string, HTMLImageElement>(
      ((loader) => {
        return urls.map(url => {
          const image = new Image();
          image.onload = () => {
            // On last load, execute pending actions.
            if (--loader.remainingCount == 0) {
              loader.pendingActions.forEach(action => action(loader.images));
              loader.pendingActions.length = 0; // Not necessary, but nice.
            }
          }
          image.onerror = () => loader.errors.add(url);
          image.src = url;
          return [url, image];
        })
      })(this));
  }

  public invokeAfterLoaded(action: (images: Map<string, HTMLImageElement>) => void): void  {
    if (this.remainingCount == 0) {
      action(this.images);
    } else {
      this.pendingActions.push(action);
    }
  }
}

// Start loading the images. Put this in the component constructor.
this.loader = new ImagesLoader([
  'https://www.jqwidgets.com/wp-content/design/i/logo-jqwidgets.svg',
  'https://www.greencastonline.com/assets/img/logo.png']);

// Then we can invoke rendering in NgAfterViewInit, possibly delayed until loaded,
// and re-render as needed with the same loader.
this.loader.invokeAfterLoaded((images) => console.log("first"));
this.loader.invokeAfterLoaded((images) => console.log("second"));

我只是不想选择一种后期代码增多后需要替换的糟糕模式。

注:致编辑:此问题并非寻求主观意见,而是询问在Angular中实现该需求的正确、符合惯例且可读性强的方式,我并非Angular专家。这就是“简洁”的含义。作为工程师,我们多少次在绕远路的代码上浪费时间?能用两行代码解决却写了四十行?这会耗费时间、资金,还会影响同事间的信任与尊重。拼凑出勉强能用的代码是业余人士的做法(我提出的方案就处于这个水平)。如果SO将此类问题定义为“主观意见”,那我将不再使用该平台。我坚信半数编辑从未在团队环境中开发过重要软件。

内容的提问来源于stack exchange,提问作者Gene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 00:58:26