1
头图

在移动端和小型设备应用中,动态显示评分通常使用五角星图形更直观。本文将结合 HarmonyOS 的 OffscreenCanvas 与 OffscreenCanvasRenderingContext2D,演示如何生成可按分数填充的五角星图像。

1. OffscreenCanvas 简介

在 HarmonyOS 中,OffscreenCanvas 是一种在后台线程中进行绘制的画布对象,它不直接显示在界面上,而是生成 ImageBitmap 或 Blob 后再渲染到主线程或 UI 组件上。相比普通 Canvas,它有以下优势:

支持多线程绘制:不会阻塞主线程,提高 UI 流畅度。

灵活生成图像资源:可生成 ImageBitmap,用于 Image 组件或其他渲染场景。

适合动态图形绘制:如评分星、进度条、游戏元素等。

使用示例:

const canvas = new OffscreenCanvas(width, height);
const ctx = canvas.getContext('2d') as OffscreenCanvasRenderingContext2D;

参考:OffscreenCanvas API

2. 使用 OffscreenCanvasRenderingContext2D 绘制五角星

OffscreenCanvasRenderingContext2D 提供了丰富的绘图 API,可实现路径绘制、颜色填充和渐变效果。

在我们的示例中,需要实现如下功能:

绘制标准五角星路径;

绘制整颗灰色背景星;

根据分数比例绘制黄色填充;

返回 ImageBitmap 对象供 UI 使用。

核心代码如下:

export class CanvasUtil {
  /**
   * 生成五角星
   * @param starSize 宽高
   * @param score 分数
   * @param fullScore 总分
   * @returns 返回ImageBitmap对象,使用之后需要立即调用close防止内存泄露
   */
  static generateStar(starSize: number, score: number, fullScore: number): ImageBitmap {
    const canvas = new OffscreenCanvas(starSize, starSize);
    const ctx = canvas.getContext('2d') as OffscreenCanvasRenderingContext2D;

    // 创建五角星路径
    const createStarPath = (cx: number, cy: number, spikes: number, outer: number, inner: number) => {
      const path = new Path2D();
      let rot = Math.PI / 2 * 3;
      const step = Math.PI / spikes;
      path.moveTo(cx + Math.cos(rot) * outer, cy + Math.sin(rot) * outer);
      for (let i = 0; i < spikes; i++) {
        rot += step;
        path.lineTo(cx + Math.cos(rot) * inner, cy + Math.sin(rot) * inner);
        rot += step;
        path.lineTo(cx + Math.cos(rot) * outer, cy + Math.sin(rot) * outer);
      }
      path.closePath();
      return path;
    }

    const path = createStarPath(starSize / 2, starSize / 2, 5, starSize / 2, starSize / 4.5);

    // 绘制灰色底星
    ctx.fillStyle = getContext().resourceManager.getColorSync($r("app.color.star_blank_color"));
    ctx.fill(path);

    // 根据 score 绘制黄色填充
    if (score > 0) {
      const ratio = Math.min(Math.max(score / fullScore, 0), 1); // 限制 0~1
      ctx.save();
      ctx.beginPath();
      ctx.clip(path); // 限制填充在星形内

      const grad = ctx.createLinearGradient(0, starSize, 0, 0);
      grad.addColorStop(0, getContext().resourceManager.getColorSync($r("app.color.star_fill_color")).toString());
      grad.addColorStop(ratio, getContext().resourceManager.getColorSync($r("app.color.star_fill_color")).toString());
      grad.addColorStop(ratio, getContext().resourceManager.getColorSync($r("app.color.star_blank_color")).toString());
      grad.addColorStop(1, getContext().resourceManager.getColorSync($r("app.color.star_blank_color")).toString());

      ctx.fillStyle = grad;
      ctx.fill(path);
      ctx.restore();
    }

    // 返回 ImageBitmap
    return ctx.transferToImageBitmap();
  }
}

3. 使用注意事项

内存管理:生成 ImageBitmap 后,使用完成需要调用 close() 释放内存。

线程安全:OffscreenCanvas 可在工作线程中绘制,避免阻塞 UI。

渐变填充:通过 clip() 限制填充范围,实现分数按比例显示。
参考:OffscreenCanvasRenderingContext2D API

4. 总结

通过 OffscreenCanvas 与 OffscreenCanvasRenderingContext2D,我们可以在 HarmonyOS 中轻松实现动态五角星评分效果:

支持多线程绘制;

按分数比例填充颜色;

高效生成可复用图像资源。

这为开发评分组件、游戏 UI 或进度显示提供了灵活且高性能的解决方案。


Josie
29 声望8 粉丝