纹渊 HarmonyOS 7 工程实战(02):Canvas 曲面纹样渲染与重绘控制

一、问题与目标

纹渊的纹样不是简单贴一张平面图。用户选择纹样后,需要在杯体这种带弧度的载体上看到预览效果;如果直接按矩形绘制,图案会显得生硬,边缘也容易和杯身透视不一致。

Canvas 在这里承担的是“轻量预览层”的角色。它不负责最终 3D 渲染,却要在用户选择纹样、切换载体、调整模式时快速给出反馈。曲面映射、重绘时机和状态同步如果没有处理好,用户会看到旧图残留、选中态错乱或预览闪动。

运行界面

二、实现思路

实现时可以把绘制拆成三步:先把纹样资源归一化成可绘制对象,再按杯体区域切成多条竖向 band,最后根据 band 的位置计算宽度压缩和透明边缘。这样虽然不是完整 3D 投影,但足够表达杯身弧度。

重绘触发点要少而明确。纹样变更、载体变更、画布尺寸变化和模式切换会触发绘制;普通页面刷新不应该重复创建资源。否则在平板或 2in1 上频繁调整窗口时,预览层容易出现抖动。

绘制环节处理方式
资源准备把纹样图片、默认底图和空状态统一成可绘制对象
曲面切片按横向位置拆分 band,用宽度和透明度模拟杯体弧度
重绘控制只在纹样、载体或尺寸变化时触发 Canvas 刷新
结果输出预览图可以继续交给导出、分享或 3D 材质链路

三、关键实现

曲面效果的关键在 band 的宽度和位置计算。下面这个片段把杯身分成多个窄条,每个窄条按自身所在位置做压缩,最终形成类似包裹在杯面上的视觉效果。

private drawCurvedBands(ctx: CanvasRenderingContext2D): void {
  const bandCount = 21
  const bandWidth = this.canvasWidth / bandCount
  for (let i = 0; i < bandCount; i++) {
    const u = this.cupWarpU(i)
    const scaleX = 0.72 + Math.sin(u * Math.PI) * 0.28
    const alpha = 0.42 + Math.sin(u * Math.PI) * 0.5
    ctx.save()
    ctx.globalAlpha = alpha
    ctx.translate(i * bandWidth + bandWidth / 2, 0)
    ctx.scale(scaleX, 1)
    ctx.drawImage(this.patternImage, -bandWidth / 2, 0, bandWidth, this.canvasHeight)
    ctx.restore()
  }
}

这段逻辑的好处是计算成本低,不需要加载 3D 场景也能给出接近载体形状的反馈。对于创作页来说,用户最先需要判断的是纹样方向、密度和色块关系是否合适,Canvas 预览足够承担这个即时反馈。

需要注意的是,Canvas 绘制结果必须和页面状态绑定,而不是和某一次点击绑定。用户连续切换纹样时,旧绘制任务应该被新状态覆盖;否则看似只是慢半拍,实际会让后续导出或 3D 贴图拿到错误纹样。

四、失败场景与取舍

Canvas 预览最容易出现三类问题:资源尚未加载就开始绘制,导致空白;窗口尺寸变化后没有重新计算 band,导致变形;用户快速切换纹样时旧结果覆盖新结果,导致选中态和预览不一致。

取舍上,创作页不需要在 Canvas 层追求真实物理投影,而要优先保证反馈速度和状态一致。精细材质效果交给 3D 预览,Canvas 负责低成本确认图案方向和整体观感,两层职责分开后,问题会更容易定位。

五、验证步骤

  1. 打开创作入口,确认标题、主要卡片、底部操作区和预览区域显示正常。
  2. 走一遍主流程,观察加载态、成功态和下一步按钮是否同步变化。
  3. 人为制造空输入、重复点击或不可用条件,确认页面给出可理解的提示。
  4. 返回上一页再进入,确认选中态、预览结果和关键状态没有漂移。
  5. 在较窄窗口和较宽窗口各看一遍,确认文字、卡片和按钮没有重叠。

六、总结

Canvas 曲面预览的重点是快速、稳定、可恢复。只要资源准备、曲面切片和重绘触发点清楚,创作页就能在不依赖完整 3D 场景的情况下给用户可靠反馈。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值