HarmonyOS7 Canvas 文字怎么画得清楚:CanvasTextStyling 实战说明
文章目录
前言

很多人学 Canvas,最先想到的都是图形。但到了真实业务里,真正决定画面是不是“能用”的,常常不是方块和圆,而是字。你图形画得再顺,标题摆不齐、标签不清楚、数值看着别扭,这个画布照样不专业。
这篇就专门讲 Canvas 里的文字绘制。案例覆盖的内容很基础,但也正因为基础,特别适合拿来建立文字样式的控制感。
这个案例重点不在内容,在样式组合
页面上依次展示了几种文字效果:

- 普通填充文字
- 描边文字
- 粗体文字
- 居中文字
- 小字号辅助文字
你可以把这一页理解成一个最小文字样式实验台。重点不是这些文案写了什么,而是同一块画布里,字体、大小、颜色、对齐方式怎么配合使用。
完整代码
import { DEMO_BG_COLOR, DEMO_CARD_COLOR, DEMO_THEME_COLOR, DEMO_SUBTEXT_COLOR } from './types'
@Entry
@Component
struct CanvasTextStyling {
@State isShow: boolean = true
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Column() {
if (this.isShow) {
Scroll() {
Column({ space: 16 }) {
Text('Canvas 文字绘制').fontSize(16).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)
Column() {
Text('文字绘制效果').fontSize(13).fontColor('#4D96FF').margin({ bottom: 8 })
Column() {
Canvas(this.context)
.onReady(() => {
let y = 30
this.context.font = '18px sans-serif'
this.context.fillStyle = '#4D96FF'
this.context.fillText('fillText 填充文字', 10, y)
y += 35
this.context.font = '20px sans-serif'
this.context.strokeStyle = '#FF6B6B'
this.context.lineWidth = 1
this.context.strokeText('strokeText 描边文字', 10, y)
y += 35
this.context.font = 'bold 22px sans-serif'
this.context.fillStyle = '#FFA500'
this.context.fillText('bold 粗体文字', 10, y)
y += 40
this.context.font = '14px sans-serif'
this.context.fillStyle = '#6BCB77'
this.context.textAlign = 'center'
this.context.fillText('textAlign: center 居中', 190, y)
y += 30
this.context.font = '12px sans-serif'
this.context.fillStyle = '#999999'
this.context.textAlign = 'left'
this.context.fillText('font: "12px sans-serif" 设置字体', 10, y)
})
.width('100%')
.height(200)
.backgroundColor('#F0F0F0')
.borderRadius(8)
}
}
.backgroundColor(DEMO_CARD_COLOR)
.padding(12)
.borderRadius(12)
Column({ space: 6 }) {
Text('文字绘制 API').fontSize(14).fontColor(DEMO_THEME_COLOR).fontWeight(FontWeight.Bold)
Text('context.font = "16px sans-serif" - 设置字体').fontSize(12).fontColor('#333333')
Text('context.fillStyle = "#333" - 设置填充颜色').fontSize(12).fontColor('#333333')
Text('context.fillText(text, x, y) - 填充文字').fontSize(12).fontColor('#333333')
Text('context.strokeText(text, x, y) - 描边文字').fontSize(12).fontColor('#333333')
Text('context.textAlign = "center"/"left"/"right" - 对齐').fontSize(12).fontColor('#333333')
Text('context.textBaseline = "top"/"middle"/"bottom" - 基线').fontSize(12).fontColor('#333333')
Text('context.measureText(text).width - 测量文字宽度').fontSize(12).fontColor('#333333')
}
.width('100%')
.backgroundColor('#E8F4FD')
.padding(14)
.borderRadius(12)
}
.width('100%')
}
}
Text('CanvasTextStyling - fillText 与 strokeText')
.fontSize(12)
.fontColor(DEMO_SUBTEXT_COLOR)
.margin({ top: 12 })
}
.width('100%')
.height('100%')
.backgroundColor(DEMO_BG_COLOR)
.padding(16)
}
}

先搞清楚:文字也是画出来的
在普通 ArkUI 组件里,Text() 是声明式组件;但到了 Canvas 里,文字不是组件,而是一种绘制结果。
这意味着两件事。
第一,你得自己决定每一行字的坐标。
第二,样式不会自动分层,字号、粗细、颜色、对齐都要你手动控制。
案例里用一个 y 变量逐行推进:
let y = 30
this.context.fillText('fillText 填充文字', 10, y)
y += 35
这是最适合入门的写法,因为你能非常明确地看到“下一行为什么会跑到下面去”。
font 是整套文字样式的入口
案例几乎每画一段文字前,都会先改 font:
this.context.font = '18px sans-serif'
this.context.font = '20px sans-serif'
this.context.font = 'bold 22px sans-serif'
这里别只把它当成字号设置。font 字符串本质上是一次性描述文字样式的入口,里面可以包含粗细、字号、字体族。
比如:
'18px sans-serif'是普通 18 像素无衬线字体'bold 22px sans-serif'是粗体 22 像素无衬线字体
如果你要在同一块画布里做标题、正文、说明、数值,这个属性会频繁切换。
fillText() 和 strokeText() 的区别
案例把这两个方法并排演示,非常适合对比理解。
fillText()
this.context.fillStyle = '#4D96FF'
this.context.fillText('fillText 填充文字', 10, y)
这是最常用的文字绘制方式。它画出来的是实心字,适合绝大多数正文、标题、数值标签。
strokeText()
this.context.strokeStyle = '#FF6B6B'
this.context.lineWidth = 1
this.context.strokeText('strokeText 描边文字', 10, y)
这画出来的是轮廓字。它不适合大段正文,但在海报标题、装饰字、特殊提示上会有用。
你可以把它理解成一种更强调视觉风格的文字表现,而不是信息密度最高的那种文字。
textAlign 会直接影响你怎么找坐标
案例里有一段居中文字:
this.context.textAlign = 'center'
this.context.fillText('textAlign: center 居中', 190, y)
这句代码的重点,不只是把字居中,而是告诉你:当对齐方式变化后,传进去的 x 坐标代表的意义也变了。
left时,x是文字左边缘center时,x是文字中心right时,x是文字右边缘
如果你后面要做图表标题、柱状图标签、卡片中心文案,这个概念必须熟。
为什么案例最后又把 textAlign 改回 left
这一段其实特别像真实开发:
this.context.textAlign = 'left'
this.context.fillText('font: "12px sans-serif" 设置字体', 10, y)
因为 Canvas 上下文是有状态的。你一旦把 textAlign 改成 center,后面如果不改回来,接下来的文字都会继续按照居中逻辑去画。
这也是 Canvas 初学者最容易被坑的点之一:属性不是只影响当前一行,而是会保留到你下一次改掉它为止。
measureText() 为什么值得提前知道
案例虽然没有真的调用,但把这个 API 列出来了:
context.measureText(text).width
这个方法在真实项目里很实用。比如你要:
- 动态计算标签宽度
- 判断某段文字会不会超出画布
- 让图表数值精确居中
- 根据内容长度画背景气泡
只靠经验猜宽度,后面很容易翻车。能测量,就别拍脑袋。
这类画布文字最常见的使用场景
我最常见的几个场景是:
- 图表标题和数值标签
- 海报文案和价格展示
- 进度面板里的状态说明
- 签名板、标注板里的辅助文字
这些地方的共同点是,文字和图形不是分开的,而是要一起组成一个画面。所以你不能只会“显示文字”,还得会控制它和图形之间的关系。
容易踩的坑
第一个坑,是忘了不同样式之间要重新设置 font。
第二个坑,是 textAlign 改了以后没恢复,后面的字全部歪掉。
第三个坑,是只关注字号,不关注行距,结果文字一多就挤成一团。
第四个坑,是在 Canvas 里还拿普通组件排版的思维来想,结果越画越乱。
写在最后
Canvas 里的文字绘制,说到底是在训练你对“视觉信息层级”的控制力。标题该大、说明该浅、标签该对齐、数值该稳,这些都不是默认送你的,而是你一笔一笔配出来的。
把这一页吃透,后面你再做图表、海报或者复杂状态面板,画面会一下子专业很多。
更多推荐


所有评论(0)