ArkUI Shape:不用切图,也能画出页面的骨架
【摘要】 今天我们先不碰复杂绘图,只把 Shape 当成一块轻量画板来用。页面里那些小背景、小标识、小装饰线,如果每次都切图,维护起来会很累;用 Shape 直接画,很多时候更省事。 先看这个页面画了什么 这个 Demo 分成四块: 第一块把 Rect、Circle、Path 放进同一个 Shape 里,先建立“容器 + 子图形
ArkUI Shape:不用切图,也能画出页面的骨架
今天我们先不碰复杂绘图,只把 Shape 当成一块轻量画板来用。页面里那些小背景、小标识、小装饰线,如果每次都切图,维护起来会很累;用 Shape 直接画,很多时候更省事。
先看这个页面画了什么
这个 Demo 分成四块:
- 第一块把
Rect、Circle、Path放进同一个Shape里,先建立“容器 + 子图形”的感觉。 - 第二块对比
fill和stroke,一个管内部颜色,一个管边线。 - 第三块看
strokeWidth,同一条曲线换个线宽,存在感会完全不同。 - 第四块看
antiAlias,斜线和曲线一般建议打开抗锯齿。
我们写这类页面时,不需要急着上 Canvas。Shape 更像轻量矢量区域,适合把简单视觉元素留在 ArkUI 里维护。
Shape 容器
核心代码长这样:
Shape() {
Rect({ width: 150, height: 72, radius: 18 })
.fill('#DBEAFE')
.stroke('#2563EB')
.strokeWidth(3)
Circle({ width: 54, height: 54 })
.fill('#F97316')
Path()
.commands('M34 122 L82 72 L130 122 Z')
.fill('#0F766E')
}
.height(150)
.viewPort({ x: 0, y: 0, width: 220, height: 150 })
viewPort 可以理解成这块小画板的坐标范围。我们把图形放进去之后,点位、尺寸和偏移会更好控制。
什么时候用它
如果只是画几何图形、标签底、卡片里的装饰线,Shape 很合适。它比切图灵活,也比 Canvas 少一点心智负担。等你要做自由绘制、动态图表、复杂路径运算时,再去看 Canvas 会更顺。
你平时做页面时,有没有为了一个很小的装饰元素专门切过图?这种场景大概率就可以先试试 Shape。
参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-shape-overview
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/drawing/ArkUIShapeOverviewDemo.ets
@Entry
@Component
struct ArkUIShapeOverviewDemo {
@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)
}
@Builder
sampleLabel(text: string) {
Text(text)
.fontSize(12)
.fontColor('#475569')
.textAlign(TextAlign.Center)
.width('100%')
}
build() {
Scroll() {
Column({ space: 18 }) {
Text('ArkUI Shape')
.width('100%')
.fontSize(24)
.fontWeight(700)
.fontColor('#0F172A')
Text('不用切图,也能画出页面的骨架')
.width('100%')
.fontSize(22)
.fontWeight(700)
.fontColor('#111827')
Text('这一页先看 Shape 容器。它适合画轻量矢量图形:背景块、装饰线、简单标识、卡片里的小插画,都可以先不用切图。')
.width('100%')
.fontSize(14)
.fontColor('#64748B')
.lineHeight(22)
Column({ space: 12 }) {
this.sectionTitle('Shape 像一个小画板', '我们可以把 Rect、Circle、Path 放进 Shape 里,用统一的尺寸和坐标感组织它们。')
Shape() {
Rect({ width: 150, height: 72, radius: 18 })
.fill('#DBEAFE')
.stroke('#2563EB')
.strokeWidth(3)
.offset({ x: 16, y: 18 })
Circle({ width: 54, height: 54 })
.fill('#F97316')
.stroke('#FED7AA')
.strokeWidth(4)
.offset({ x: 126, y: 28 })
Path()
.commands('M34 122 L82 72 L130 122 Z')
.fill('#0F766E')
.stroke('#134E4A')
.strokeWidth(2)
}
.width('100%')
.height(150)
.viewPort({ x: 0, y: 0, width: 220, height: 150 })
}
.width('100%')
.padding(16)
.backgroundColor('#EFF6FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('fill 和 stroke 先分清', 'fill 管内部颜色,stroke 管边线。很多轻量图形只靠这两个属性,就能从占位块变成真正的视觉元素。')
Row({ space: 12 }) {
Column({ space: 8 }) {
Shape() {
Rect({ width: 96, height: 72, radius: 16 })
.fill('#DCFCE7')
.stroke('#16A34A')
.strokeWidth(4)
}
.width(110)
.height(86)
this.sampleLabel('有填充也有描边')
}
.layoutWeight(1)
Column({ space: 8 }) {
Shape() {
Circle({ width: 72, height: 72 })
.fill('#FEF3C7')
.stroke('#D97706')
.strokeWidth(6)
}
.width(110)
.height(86)
this.sampleLabel('圆形也一样')
}
.layoutWeight(1)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor('#F0FDF4')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('strokeWidth 决定边线存在感', '边线太细像没画,太粗又会抢内容。Demo 里故意放了两个宽度,方便你一眼看出差别。')
Row({ space: 12 }) {
Column({ space: 8 }) {
Shape() {
Path()
.commands('M18 68 C44 18 92 18 118 68')
.stroke('#7C3AED')
.strokeWidth(2)
}
.width(136)
.height(82)
.viewPort({ x: 0, y: 0, width: 136, height: 82 })
this.sampleLabel('strokeWidth(2)')
}
.layoutWeight(1)
Column({ space: 8 }) {
Shape() {
Path()
.commands('M18 68 C44 18 92 18 118 68')
.stroke('#7C3AED')
.strokeWidth(8)
}
.width(136)
.height(82)
.viewPort({ x: 0, y: 0, width: 136, height: 82 })
this.sampleLabel('strokeWidth(8)')
}
.layoutWeight(1)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor('#F5F3FF')
.borderRadius(8)
Column({ space: 12 }) {
this.sectionTitle('antiAlias 让斜线边缘更顺', '一般来说我们会保持抗锯齿开启。它不是万能美化,但对斜线、曲线、圆形边缘很有帮助。')
Row({ space: 12 }) {
Column({ space: 8 }) {
Shape() {
Path()
.commands('M16 72 L118 16')
.stroke('#C2410C')
.strokeWidth(9)
}
.width(136)
.height(88)
.antiAlias(false)
this.sampleLabel('antiAlias(false)')
}
.layoutWeight(1)
Column({ space: 8 }) {
Shape() {
Path()
.commands('M16 72 L118 16')
.stroke('#C2410C')
.strokeWidth(9)
}
.width(136)
.height(88)
.antiAlias(true)
this.sampleLabel('antiAlias(true)')
}
.layoutWeight(1)
}
.width('100%')
}
.width('100%')
.padding(16)
.backgroundColor('#FFF7ED')
.borderRadius(8)
}
.width('100%')
.padding(20)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#FFFFFF')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)