ArkUI Canvas:画布一开,页面终于能自己动笔
【摘要】 这一篇我们只做 Canvas 入门。不开动画循环,不做离屏绘制,也不处理图片像素;先把最基础的 2D 绘制跑通。 Canvas 和 Shape 的区别 Shape 更像声明式小图形,适合简单矢量元素。Canvas 更像一张画纸,我们拿到 CanvasRenderingContext2D 后,用命令一笔一笔画。 Demo
ArkUI Canvas:画布一开,页面终于能自己动笔
这一篇我们只做 Canvas 入门。不开动画循环,不做离屏绘制,也不处理图片像素;先把最基础的 2D 绘制跑通。
Canvas 和 Shape 的区别
Shape 更像声明式小图形,适合简单矢量元素。Canvas 更像一张画纸,我们拿到 CanvasRenderingContext2D 后,用命令一笔一笔画。
Demo 里只画了四类东西:
fillRect和strokeRect:左上角的矩形。arc:右上角的圆。moveTo和lineTo:中下方的折线。fillText:左下角的文字。
context 不要写成状态
这里有个很实际的坑:CanvasRenderingContext2D 和 RenderingContextSettings 是绘制上下文,不是页面状态。我们把它们写成普通私有字段就好。
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
真正绘制的动作放在 onReady 里:
Canvas(this.context)
.width(320)
.height(220)
.onReady(() => {
this.drawCanvas();
})
onReady 表示画布准备好了。这时候再调 fillRect、arc、fillText,才不会出现上下文还没准备好就开始画的问题。
先画一次就够了
这一篇是第一步,所以我们只画一次。后面如果要做动画、图表、手写板,再考虑定时刷新、手势输入、性能和离屏绘制。入门时先别把这些全塞进来。
你最想用 Canvas 画什么?小图表、签名板、游戏元素,还是某个业务里的自定义装饰?这个答案会决定下一步该补哪一类能力。
参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-drawing-customization-on-canvas
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/drawing/ArkUICanvasDemo.ets
@Entry
@Component
struct ArkUICanvasDemo {
private settings: RenderingContextSettings = new RenderingContextSettings(true);
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);
private drawCanvas() {
this.context.clearRect(0, 0, 320, 220);
this.context.fillStyle = '#F8FAFC';
this.context.fillRect(0, 0, 320, 220);
this.context.fillStyle = '#DBEAFE';
this.context.fillRect(24, 24, 120, 72);
this.context.strokeStyle = '#2563EB';
this.context.lineWidth = 4;
this.context.strokeRect(24, 24, 120, 72);
this.context.beginPath();
this.context.arc(232, 62, 36, 0, 2 * Math.PI);
this.context.fillStyle = '#DCFCE7';
this.context.fill();
this.context.strokeStyle = '#0F766E';
this.context.lineWidth = 4;
this.context.stroke();
this.context.beginPath();
this.context.moveTo(36, 166);
this.context.lineTo(112, 126);
this.context.lineTo(198, 168);
this.context.lineTo(284, 120);
this.context.strokeStyle = '#C2410C';
this.context.lineWidth = 5;
this.context.stroke();
this.context.fillStyle = '#111827';
this.context.font = 'bold 18px sans-serif';
this.context.fillText('Canvas', 24, 206);
}
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 4 }) {
Text(title)
.width('100%')
.fontSize(16)
.fontWeight(700)
.fontColor('#0F172A')
Text(desc)
.width('100%')
.fontSize(13)
.fontColor('#64748B')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
build() {
Scroll() {
Column({ space: 18 }) {
Text('ArkUI Canvas')
.width('100%')
.fontSize(24)
.fontWeight(700)
.fontColor('#0F172A')
Text('画布一开,页面终于能自己动笔')
.width('100%')
.fontSize(22)
.fontWeight(700)
.fontColor('#111827')
Text('Canvas 更像一张真正的画纸。我们拿到 2D 上下文后,在 onReady 里画矩形、圆弧、折线和文字。')
.width('100%')
.fontSize(14)
.fontColor('#64748B')
.lineHeight(22)
Column({ space: 12 }) {
this.sectionTitle('先准备 CanvasRenderingContext2D', 'RenderingContextSettings 用来创建 2D 绘制上下文。注意这里不要把 context 写成 @State,它不是页面状态。')
Canvas(this.context)
.width(320)
.height(220)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#CBD5E1' })
.borderRadius(8)
.onReady(() => {
this.drawCanvas();
})
}
.width('100%')
.padding(16)
.backgroundColor('#EFF6FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('这一张画布里画了什么', 'fillRect 画填充矩形,strokeRect 画边框矩形,arc 画圆弧,moveTo 和 lineTo 连出折线,fillText 写文字。')
Column({ space: 10 }) {
Text('fillRect + strokeRect:左上角的蓝色矩形')
.fontSize(13)
.fontColor('#475569')
Text('beginPath + arc:右上角的绿色圆')
.fontSize(13)
.fontColor('#475569')
Text('moveTo + lineTo:中下方的橙色折线')
.fontSize(13)
.fontColor('#475569')
Text('fillText:左下角的 Canvas 文字')
.fontSize(13)
.fontColor('#475569')
}
.width('100%')
.padding(14)
.backgroundColor('#FFFFFF')
.borderRadius(8)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.padding(16)
.backgroundColor('#F8FAFC')
.borderRadius(8)
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)