JS 生成文字头像

239 阅读1分钟
export class Avatar {
  // 昵称
  nickname: string = '用户';
  // 字体大小
  fontSize: number = 32;
  // 尺寸
  size: number = 100;
  // 颜色数组
  colors: string[] = ['#1677ff'];
  // 字体粗细
  fontWeight: string = 'normal';

  // 私有属性,画布元素
  private canvas: HTMLCanvasElement | null = null;
  // 私有属性,2D 绘图上下文
  private ctx: CanvasRenderingContext2D | null = null;

  /**
   * 构造函数,可接收部分属性进行初始化
   * @param args 包含部分属性的对象
   */
  constructor(args?: Partial<Avatar>) {
    Object.assign(this, args);
    this.init();
  }

  /**
   * 初始化方法,创建画布并获取上下文
   */
  private init(): void {
    this.canvas = document.createElement('canvas');
    this.canvas.width = this.size;
    this.canvas.height = this.size;
    this.ctx = this.canvas.getContext('2d');
  }

  /**
   * 渲染方法,生成头像
   * @param name 可选的昵称
   * @param color 可选的背景颜色
   * @returns 生成的 HTMLCanvasElement
   */
  private render(name?: string, color?: string): HTMLCanvasElement {
    if (!this.canvas || !this.ctx) {
      throw new Error('画布或上下文未正确初始化,请检查相关代码。');
    }

    // 清除画布
    this.clearCanvas();

    const avatarName = this.getAvatarName(name);
    const bgColor = color || this.getRandomColor();

    this.drawBackground(bgColor);
    this.drawText(avatarName);

    return this.canvas;
  }

  /**
   * 创建头像并返回 DataURL 字符串
   * @ name 可选的昵称
   * @param color 可选的背景颜色
   * @returns 头像的 DataURL 字符串
   */
  create(name?: string, color?: string): string {
    const canvas = this.render(name, color);
    return canvas.toDataURL('image/png');
  }

  /**
   * 创建头像并返回 Promise
   * @param name 可选的昵称
   * @param color 可选的背景颜色
   * @returns 包含 Blob URL 的 Promise
   */
  createAsync(name?: string, color?: string): Promise<string> {
    const canvas = this.render(name, color);
    return new Promise((resolve, reject) => {
      canvas.toBlob((blob) => {
        if (blob) {
          resolve(URL.createObjectURL(blob));
        } else {
          reject(new Error('创建 Blob 失败,请检查相关代码。'));
        }
      }, 'image/png');
    });
  }

  /**
   * 获取头像显示的昵称
   * @param name 可选的输入昵称
   * @returns 处理后的昵称
   */
  private getAvatarName(name?: string): string {
    const avatarName = name || this.nickname;
    return avatarName.length > 2 ? avatarName.slice(-2) : avatarName;
  }

  /**
   * 获取随机颜色
   * @returns 随机的颜色字符串
   */
  private getRandomColor(): string {
    return this.colors[Math.floor(Math.random() * this.colors.length)];
  }

  /**
   * 绘制背景
   * @param color 背景颜色
   */
  private drawBackground(color: string): void {
    if (!this.ctx) return;
    this.ctx.fillStyle = color;
    this.ctx.fillRect(0, 0, this.size, this.size);
  }

  /**
   * 绘制文本
   * @param text 要绘制的文本
   */
  private drawText(text: string): void {
    if (!this.ctx) return;
    this.ctx.fillStyle = '#FFFFFF';
    this.ctx.font = `${this.fontWeight} ${this.fontSize}px serif`;
    this.ctx.textAlign = 'center';
    this.ctx.textBaseline = 'middle';
    this.ctx.fillText(text, this.size / 2, this.size / 2);
  }

  /**
   * 清除画布
   */
  private clearCanvas(): void {
    if (!this.ctx || !this.canvas) return;
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
  }
}