仓储现场补打一张工作单时,最容易出现的讨论往往不是“文字有没有显示”,而是“这条边缘到底有没有变化”。这类问题不能靠肉眼印象下结论。字号、字重、文本内容、画布大小只要一起变化,看到的差异就失去归属。

当前页面工程把这件事收得很窄:它绘制一条工作单文本,同时保留“当前画面”和“上次快照”。每次修改字号、字重、文本、抗锯齿状态或观察倍率前,页面先保存上一组参数;改变抗锯齿后,再把两组状态各自绘制出来。读者要做的不是判断哪一种更好看,而是确认本次对照是否只改变了一个变量。

【插图位置 01|页面基线】插入页面初始状态:当前画面显示“工单 WO-6101”,上次快照区域显示等待提示,底部可见观察倍率、字号、字重和抗锯齿选择器。

场景解说:该画面证明页面已准备好记录一次参数变化前后的本地绘制状态;它不能证明补印文件已生成、已发送到打印机或仓储数据已更新。

标签边缘的观察条件

1. 为什么先看同一段工作单文本

页面预置了“工单 WO-6101”“验收结论:通过”“设备编号 A-081”三组文本。它们用于切换绘制输入,但不应该和抗锯齿切换混在同一轮比较里。

例如,准备观察 WO-6101 中的圆弧、斜线或数字边缘时,先固定文本、字号和字重。随后只改抗锯齿状态。这样,当前画面与上次快照之间的差异才有一个明确来源。

2. 当前画面和上次快照分别说明什么

页面并没有用两张互不相关的画布模拟对照,而是在同一个 Canvas 上分上下两块区域:上方绘制当前状态,下方绘制参数变化前保存的快照。第一次进入时没有旧快照,下方只显示等待提示;发生一次参数变化后,下方才开始绘制“上次快照”。

private capturePreviousSnapshot(): void {
  this.previousSnapshot = this.currentSnapshot();
  this.hasPreviousSnapshot = true;
}

private selectAntialias(index: number): void {
  this.capturePreviousSnapshot();
  this.antialiasIndex = index;
  this.toggleAntialias(index === 0);
}

这段代码能证明:切换前的文本、字号、字重、抗锯齿状态和观察倍率会作为一个整体被保留。它不能证明下方画面是任何打印设备的历史输出,更不能说明两个画面来自不同设备。

【插图位置 02|对照条件】插入一次只切换抗锯齿前后的页面画面,两个区域使用同一工作单文本、同一字号和同一字重。

场景解说:该画面证明本轮对照存在前一状态与当前状态;它不能单独证明肉眼差异在所有屏幕上都相同。

让这次对照有效

1. 四个条件不要一起动

一次对照至少固定四项:

  1. 工作单文本保持不变。
  2. 字号保持不变。
  3. 字重保持不变。
  4. 页面可用区域保持不变。

这里的“观察倍率”还需要特别说明:当前页面把它保存在快照和状态文案中,用于标记本轮观察参数;现有绘制逻辑不会据此对画布做像素级放大。因此它可以帮助回看本次选择,不能被写成已经实现的放大镜效果。

2. 一次看似合理、实际作废的比较

如果先把字号从 84px 调到 112px,随后又关闭抗锯齿,当前画面与上次快照必然不同,但差异同时来自字号和渲染参数。这时不能得出“关闭抗锯齿让文字变成某种样子”的结论。

正确的恢复方法很简单:切回同一文本、同一字号和同一字重,再重新执行一次抗锯齿切换。页面每一次参数选择都会先保存上一次快照,因此读者不需要靠记忆回想上一个状态。

【插图位置 03|无效对照提醒】插入字号或字重已改变、页面提示读者需要重新建立单变量对照的状态画面。

场景解说:该画面用于说明为什么本轮比较不能归因于抗锯齿;它不是页面或系统报错画面。

抗锯齿开关怎样进入绘制过程

1. 状态写入 Canvas 上下文

选择“开启”或“关闭”后,页面把布尔状态写入当前 Canvas 的渲染上下文,并更新一条可读状态。写入失败时,状态会回退到原来的选择,不会留下“按钮显示已切换、绘制条件却未知”的状态。

private applyAntialias(ctx: CanvasRenderingContext2D, enabled: boolean): boolean {
  try {
    ctx.antialias = enabled;
    return true;
  } catch (_error) {
    this.antialiasStatus = '当前运行环境不支持动态抗锯齿';
    return false;
  }
}

private toggleAntialias(enabled: boolean): void {
  const previous = this.antialiasEnabled;
  this.antialiasEnabled = enabled;
  if (this.applyAntialias(this.context, enabled)) {
    this.antialiasStatus = enabled ?
      '抗锯齿已开启:边缘使用过渡像素' :
      '抗锯齿已关闭:边缘呈现硬边界';
  } else {
    this.antialiasEnabled = previous;
    this.antialiasIndex = previous ? 0 : 1;
    this.applyAntialias(this.context, previous);
  }
  this.renderCanvas();
}

这段代码能证明运行时存在一个可切换的文本抗锯齿状态,并且失败时会恢复旧状态。它不能证明设备屏幕上的视觉差异一定明显,也不能替代打印成品或字体质量验收。

2. 为什么当前画面和上次快照各自写入状态

绘制面板时,页面从快照中取出对应的 antialiasEnabled,再将其写入上下文。因此,上下两个区域不是拿同一组最新参数重复画两遍,而是分别还原当前状态和前一状态。

private drawSnapshotPanel(snapshot: SnapshotState, x: number, y: number,
  width: number, height: number, title: string, accent: string): void {
  const text = this.shortenedText(snapshot.sampleText);
  this.applyAntialias(this.context, snapshot.antialiasEnabled);
  // 根据 snapshot 的字号、字重与文本绘制面板
}

这里能证明上次快照保留的是一组可重绘的参数,而不是一张已经保存的位图。它不能证明两次绘制之间没有运行时差异,所以文章中应把它称作“页面工程内的参数对照”,而不是跨设备基准测试。

【插图位置 04|抗锯齿切换结果】插入“当前画面”为关闭、“上次快照”为开启的同文本对照,底部同时露出抗锯齿状态和渲染状态。

场景解说:该画面证明页面把两组状态分别用于本地绘制;它不能推导出关闭或开启在所有设备上的视觉优劣。

画布就绪与结果判断

1. 先有可用尺寸,才有一次有效绘制

画布区域变化时,页面会更新宽高;画布真正准备完成后才将 canvasReady 置为可用并触发绘制。绘制方法在开头检查这一状态,避免零尺寸区域被误当成渲染结果。

private renderCanvas(): void {
  if (!this.canvasReady) {
    return;
  }
  // 计算上下两个面板的位置并绘制当前状态与上次快照
}

Canvas(this.context)
  .onAreaChange((_oldArea: Area, newArea: Area) => {
    const width = Math.floor(Number(newArea.width));
    const height = Math.floor(Number(newArea.height));
    if (width > 0 && height > 0) {
      this.canvasWidth = width;
      this.canvasHeight = height;
    }
    this.renderCanvas();
  })
  .onReady(() => {
    this.canvasReady = true;
    this.renderCanvas();
  });

这段代码能证明页面将“画布已经准备好”和“开始绘制”分开处理。它不能证明每一帧都已在某台设备上完成显示;页面状态、模拟器截图和设备视觉结论仍属于不同证据层。

2. 这一页最终能得出什么

在页面工程中,可以确认以下事实:抗锯齿状态能够被选择、上一组参数能够保留、当前状态和上一状态会被重新绘制、状态文案会回显本地运行结果。

不能越过的结论同样重要:页面没有打印调用,没有库存同步,也没有跨设备视觉验收。后续若要用于真实补印流程,仍需把工作单数据来源、打印链路和目标设备视觉检查分别接上。

【插图位置 05|画布准备与状态回显】插入画布已渲染、底部显示“已渲染 … 观察”的页面状态,必要时同时露出窄屏控制区。

场景解说:该画面证明当前 Canvas 页面已完成本地绘制与状态回显;它不能证明打印、保存或业务系统处理已经完成。

FAQ

为什么第一次进入时没有上次快照?

上次快照的职责是保留参数变化前的状态。首次进入尚未发生过参数变化,页面显示等待提示是正常状态。先修改一个参数,第二次绘制时才会出现可对照的上次状态。

为什么不同时切换字号、字重和抗锯齿?

它们都会影响字符轮廓。一次比较里同时改变多个变量,会让当前画面和上次快照虽有差异,却无法解释差异来自哪一个参数。先固定文本、字号和字重,再切抗锯齿,才是可读的单变量比较。

“观察倍率”能否用来判断边缘放大效果?

当前工程把观察倍率作为状态记录和快照参数保存,并显示在渲染状态中;它尚未参与画布缩放计算。因此它适合标记本次观察设置,不能被解释为真正的像素级放大结果。

附录:必要条件

SDK/API 与构建工具

工程需要 HarmonyOS 6.1.1 对应的 API 24 SDK、ArkTS 构建工具和能够同步依赖的开发环境。构建通过只能证明当前代码可被编译,不能证明不同设备上的文本边缘显示一致。

【插图位置|01_SDK_API构建工具.png】插入 SDK Manager 与工程构建工具版本的真实截图。

Kit 引入与页面配置

本文依赖 ArkUI Canvas、CanvasRenderingContext2D 和运行时 antialias 状态。页面必须被工程正确登记,且画布完成区域计算与就绪回调后才绘制;未就绪状态不应被记录为绘制结果。

设备权限与动态授权

本页不需要相机、麦克风、定位或通知权限。若运行期间出现权限提示,应先核实它是否来自其他能力,不能将无关权限问题归因于 Canvas 文本抗锯齿。

【插图位置|02_设备授权.png】插入测试设备的真实授权状态;若本页无动态权限,应清楚显示没有本页相关授权申请的事实。

系统能力与硬件条件

模拟器可以用于验证页面布局、参数选择、上次快照、画布就绪和本地状态回显。不同设备的屏幕密度、字体实现和显示设置可能影响肉眼感受;需要形成设备侧视觉结论时,必须在目标设备上按相同文本、字号、字重和页面尺寸补充观察记录。

【插图位置|03_运行版本与设备支持.png】插入运行版本、模拟器或目标设备信息的真实截图。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐