文章目录
- 前言:UI 升维,从“平面铺陈”到“空间折叠”
- 🏗️ 一、 Z 轴层叠布局 (ZStackLayout):用阴影与偏移雕刻空间高度
- 1.1 核心源码拆解
- 1.2 空间构建哲学与 API 解析
- 🌀 二、 3D 视角卡片网格 (PerspectiveGrid):打破屏幕的物理边界
- 2.1 核心源码拆解
- 2.2 技术深度解析
- ☁️ 三、 浮动面板 (FloatingPanel):Elevation 与弹出层级设计
- 3.1 核心源码拆解
- 3.2 鸿蒙 UI 层级规范指南
- 👆 四、 空间标签栏 (SpatialTab):状态驱动的 3D 微交互
- 4.1 核心源码拆解
- 4.2 动效设计逻辑
- 🎠 五、 立体卡片画廊 (CardGallery):多属性构建曲面阵列
- 5.1 核心源码拆解
- 5.2 组合魔法揭秘
- 📚 六、 景深列表 (DepthList):突破绝对定位的 3D 排版
- 6.1 核心源码拆解
- 6.2 布局解析与应用
- 🎯 总结与避坑指南 (Best Practices)
前言:UI 升维,从“平面铺陈”到“空间折叠”
在移动应用开发的漫长历史中,我们习惯了将 UI 元素平铺在 X 轴和 Y 轴构成的二维平面上。然而,随着 HarmonyOS NEXT 以及折叠屏、AR/VR 等新硬件形态的爆发,“空间化设计 (Spatial Design)” 已经成为顶尖 App 拉开体验差距的核心分水岭。
在空间化 UI 中,元素不再仅仅是屏幕上的色块,它们拥有了真实的物理厚度、悬浮层级(Elevation)、光影投射以及 3D 视差。引入 Z 轴后,我们可以通过视觉纵深来引导用户的注意力,打造极其高级的“微拟物”交互体验。
本文将基于一份涵盖了6 大核心空间布局场景的 ArkUI 3.0 源码,带您彻底吃透 ArkUI 中的Z轴层叠、景深 (Perspective)、3D旋转、浮动层级与空间联动动效。建议先收藏,再慢慢品读!
🏗️ 一、 Z 轴层叠布局 (ZStackLayout):用阴影与偏移雕刻空间高度
在现实世界中,叠在一起的纸牌之所以能被看出先后顺序,是因为光线产生的阴影以及视角的错位。
1.1 核心源码拆解
Stack(){// Z=3:最底层(最先声明)Column(){Text('Z=3')}.translate({x:12,y:20,z:0})// 向右下方偏移最多.shadow({radius:24,color:'#EF535040',offsetX:0,offsetY:12})// Z=2:中间层Column(){Text('Z=2')}.translate({x:6,y:10,z:0}).shadow({radius:16,color:'#AB47BC40',offsetX:0,offsetY:8})// Z=1:最顶层(最后声明)Column(){Text('Z=1(顶层)')}.translate({x:0,y:0,z:0})// 无偏移,定海神针.shadow({radius:8,color:'#5C6BC040',offsetX:0,offsetY:4})}1.2 空间构建哲学与 API 解析
- 渲染顺序即 Z 轴高度:在 ArkUI 的
Stack容器中,代码的声明顺序决定了层级。先声明的在底层,后声明的覆盖在其上。 translate的视觉欺骗:顶层卡片保持在原点(0,0),而底层卡片故意向右下方(x: 12, y: 20)偏移。这利用了透视错位,让大脑脑补出卡片是“斜向堆叠”的。- 物理真实的
shadow映射: - 顶层卡片:离底面最近,因此阴影最紧实(
radius: 8),偏移量最小(offsetY: 4)。 - 底层卡片:虽然在 DOM 树底,但通过偏移漏出来的部分,在视觉隐喻中距离光源最远,因此它的阴影必须最大、最弥散(
radius: 24,offsetY: 12)。
🌀 二、 3D 视角卡片网格 (PerspectiveGrid):打破屏幕的物理边界
在游戏商城、电影海报展示墙中,卡片以统一的角度向内侧倾斜,能营造出极强的画廊沉浸感。
2.1 核心源码拆解
Row(){// 左侧卡片:向内侧旋转Column(){Text('3D')}.rotate({x:0,y:1,z:0,angle:20,perspective:800}).shadow({radius:10,color:'#5C6BC060',offsetX:4,offsetY:6})// 中间卡片:原始平面(作为对比锚点)// ...// 右侧卡片:向内侧反向旋转Column(){Text('3D')}.rotate({x:0,y:1,z:0,angle:-20,perspective:800}).shadow({radius:10,color:'#7E57C260',offsetX:-4,offsetY:6})}2.2 技术深度解析
- 旋转轴的选择:
x: 0, y: 1, z: 0表示卡片完全绕着垂直中心轴(Y 轴)旋转,就像推开一扇门。 - **内向透视与
perspective**:左侧卡片正向旋转20°(右边缘向内陷入屏幕),右侧卡片反向旋转-20°(左边缘陷入屏幕)。最关键的是perspective: 800参数,它定义了“虚拟相机”距离屏幕的像素距离。没有这个参数,旋转看起来只是变窄的 2D 形变;加上它,就能产生近大远小的 3D 空间畸变。 - 光影的相对性:左侧卡片的阴影向右偏(
offsetX: 4),右侧阴影向左偏(offsetX: -4)。这种对全局统一中心光源的模拟,是高级 UI 不可或缺的质感来源。
☁️ 三、 浮动面板 (FloatingPanel):Elevation 与弹出层级设计
在复杂的表单或地图应用中,往往有多个浮动面板相互覆盖。如何让用户一眼看出谁在上谁在下?
3.1 核心源码拆解
Stack(){// 底层:内容页Column(){/* 主内容 */}.backgroundColor('#E8EAF6')// 中层面板 (Elevation 2)Column(){Text('中层面板')}.translate({x:0,y:-20,z:0}).shadow({radius:12,color:'#FF704040',offsetX:0,offsetY:6})// 顶层面板 (Elevation 4)Column(){Text('顶层面板')}.translate({x:-50,y:-50,z:0}).shadow({radius:20,color:'#5C6BC050',offsetX:0,offsetY:10})}3.2 鸿蒙 UI 层级规范指南
这部分代码极其精准地复刻了 Material Design 与 HarmonyOS 的Elevation(海拔)系统。
组件的 Z 轴高度不仅由Stack决定,更由shadow决定。面板悬浮得越高,意味着它对用户的优先级越高(如警告弹窗、浮动操作按钮 FAB)。
- 中层面板:阴影半径
12,投射距离6。 - 顶层面板:阴影半径激增到
20,投射距离达10。
通过这种极其规范的光影递增法则,大脑会瞬间建立起清晰的界面优先级 Z 轴树。
👆 四、 空间标签栏 (SpatialTab):状态驱动的 3D 微交互
传统的 Tab 切换只是文字变色,而空间化的 Tab 切换,按键会像真实的物理键盘一样发生形态偏转。
4.1 核心源码拆解
@Stateactive:number=0// 维护当前选中的索引ForEach(['首页','发现','我的'],(label:string,i:number)=>{Column(){Text(label)}.shadow({radius:i===this.active?12:0,// 选中时产生厚重的阴影offsetY:i===this.active?6:0}).rotate({x:0,y:i===this.active?1:0,z:0,angle:i===this.active?5:0,// 选中时微微侧转 5度perspective:500}).animation({duration:300,curve:Curve.FastOutSlowIn})// 动画缓动.onClick(()=>{this.active=i})})4.2 动效设计逻辑
这就是“状态驱动 UI”理念的巅峰体现。
我们只需要维护一个active状态。当用户点击时:
shadow瞬间从无变成有,仿佛组件从屏幕中“脱壳而出”。rotate角度从 0 变为 5 度,产生微弱的 3D 翘起效果。- 配合
.animation(Curve.FastOutSlowIn),底层的 ArkUI 引擎会自动计算属性差值,并在一帧帧中插入平滑的过渡,完美迎合用户手指按压的物理反馈。
🎠 五、 立体卡片画廊 (CardGallery):多属性构建曲面阵列
当需要展示一系列精美的特权卡或角色立绘时,平面滑动太单调。画廊模式(Gallery)通过缩放和角度的配合,创造了一个虚拟的圆柱形展台。
5.1 核心源码拆解
@Componentstruct GalleryCard{privateangle:number=0privatescale_:number=1// ...build(){Column(){Text(this.label)}// 1. 根据传入角度产生 3D 旋转.rotate({x:0,y:1,z:0,angle:this.angle,perspective:600})// 2. 两侧卡片缩小,中间卡片保持 1.0.scale({x:this.scale_,y:this.scale_})// 3. 动态阴影计算魔法.shadow({radius:8+Math.abs(this.angle)*0.5,// 角度越大,阴影越散offsetX:this.angle>0?4:-4,// 根据偏转方向决定阴影偏向offsetY:8})}}5.2 组合魔法揭秘
在CardGallery父组件中,调用了三张卡片,角度分别是-15、0、15,缩放分别是0.85、1、0.85。
scale与rotate的共舞:中间卡片最大且平正,视觉焦点最集中。两侧卡片变小且向内旋转,模拟了它们“处于更远的空间位置”。- 动态阴影的精妙算法:源码中巧妙使用了
Math.abs(this.angle) * 0.5。卡片偏转角度越大,意味着离背景墙越远,计算出的阴影半径就越大。这种通过数学公式强绑定的属性联动,是高级组件开发的必修课。
📚 六、 景深列表 (DepthList):突破绝对定位的 3D 排版
普通的 List 组件是从上往下排列的。而在某些特定的设计中(如 iOS 的通知堆叠、卡包),列表项是从远到近、从上到下像阶梯一样铺开的。
6.1 核心源码拆解
// 数据源定义了 Z 轴、阴影和 Y 轴偏移的递增关系ForEach([{label:'第四项(最深)',color:'#EF5350',shadowR:20,yOff:30},{label:'第三项',color:'#FF7043',shadowR:16,yOff:20},// ...],(item:DepthListItemInterface,index:number)=>{Column(){Text(item.label)}// 1. 位置计算:X 轴产生错位,Y 轴由配置决定.translate({x:index*4,y:item.yOff,z:0})// 2. 阴影计算:越深的项阴影越大.shadow({radius:item.shadowR,offsetX:0,offsetY:item.shadowR*0.5})// 3. 绝对定位:脱离常规文档流,使所有卡片重叠在一处.position({x:10,y:0})})6.2 布局解析与应用
- 脱离文档流:使用
.position()使得所有卡片在起始状态下重叠在左上角,这是构建层叠效果的前提。 - 多维数据驱动:通过
index * 4让 X 轴产生微小的右移,配合yOff的垂直错位,在二维屏幕上模拟出了三维空间中的“Z 轴景深”。最下方的卡片反而看起来离用户最远,非常具有视觉冲击力。
🎯 总结与避坑指南 (Best Practices)
掌握了上述 6 大场景,你几乎已经通关了 ArkUI 的空间化布局体系。为了便于实际业务开发,特总结以下性能优化原则:
- 避免重绘风暴 (Overdraw):如果一个
Stack内有数十张卡片堆叠,且都带有复杂的.shadow()。不要让底层完全不可见的卡片继续渲染,请动态给它们加上visibility(Visibility.Hidden)。 - 巧用离屏渲染加速动画:当复杂的 3D 旋转卡片(如场景五)内嵌了大量图片和文本时,务必在卡片最外层容器挂载
.renderGroup(true)。系统会将其预渲染为一张纹理,极大地降低 GPU 每一帧的计算负担,保证 60/120 FPS 的丝滑体验。 - 慎重设置 Perspective:过小的透视值(如
< 300)会导致严重的画面畸变甚至 Z 轴穿模闪烁。常规 UI 动效中,perspective保持在500 ~ 1200之间是最符合人类肉眼直觉的。
空间化设计是下一代操作系统的核心语境。学会用rotate、translate和shadow在代码中折叠空间,你就能打造出超越时代的惊艳应用。
如果这篇万字硬核实战拆解对您有帮助,恳请点赞、收藏