☰
【共创稿事节】 HarmonyOS 7从 2D 到 3D:空间计算带来的到底是什么范式变革
2026/10/1 15:44:15 网站建设 项目流程

HarmonyOS 7从 2D 到 3D:空间计算带来的到底是什么范式变革

HarmonyOS 7(API 26)里,空间计算第一次被单独拎出来当作一个板块,而不是塞在图形或媒体能力里顺手提一句。很多人第一反应是"UI 能转起来了"“能做 3D 卡片了”,但如果只把它当成视觉增强,就会漏掉真正难的部分:我们过去十年熟练的这套 2D 设计语言,在 Z 轴出现以后,有一半的默认假设都不成立了。

这篇文章想聊清楚两件事:系统级能力到底把哪些门槛抹平了,以及为什么"认知门槛"和"设计门槛"还在原地等着你。

系统把技术门槛按了下去,但没按掉认知门槛

先看系统这次到底给了什么。以前要在 App 里做真实的 3D 效果,你得自己引入渲染引擎、自己算透视矩阵、自己处理光照模型。ArkUI 现在把这些能力做进了声明式组件里:

  • 图形变换:rotate(带x/y/z旋转轴)、translate(支持z)、scale、perspective(视距)在一套属性链里就能组合出三维效果;
  • 真正的三维变换:从 API 20 起提供transform3D,可以直接喂一个 4x4 矩阵,处理带透视的变换;
  • 场景级 3D:ArkGraphics 3D 通过Component3D渲染 glTF 模型,相机、光源、材质都在 ArkTS 侧管理;
  • 端侧重建:Spatial Recon Kit 支持加载 3DGS 模型(MP4 / PLY / GLB);
  • 空间音频:AudioKit 的AudioSpatializationManager可以查询和订阅设备的空间音频渲染状态。

矩阵推导、投影、着色这些过去劝退设计师和大部分应用开发者的东西,现在被封装成了属性。这是"技术门槛下降"的真实含义。

但门槛下降的是"实现",不是"判断"。系统不会告诉你一个按钮该浮在前景还是沉到背景,不会告诉你把导航放到用户左侧 30 度意味着什么,也不会告诉你某个动效会不会让人头晕。能不能跑是工程问题,该不该这么跑是设计问题——后者才是空间计算真正的分水岭。

从 X/Y 到 X/Y/Z,改的不是多一个轴

把 2D 界面往 Z 轴一推,很多人以为只是"多了个维度"。实际变动的是整套坐标语义。

在 2D 里,屏幕的 X/Y 是位置,深度没有概念。控件要么在,要么不在;层叠靠zIndex做遮挡排序,那只是绘制顺序,用户感知不到"远近"。

到了空间里,Z 轴同时承担了四种含义:

  1. 遮挡关系——近的挡住远的,这是最表层的物理直觉;
  2. 距离感——元素离观察者多远,直接对应"重要程度"和"可交互程度";
  3. 信息层级——前景是主任务,中景是上下文,背景是环境;
  4. 注意力资源——人眼在空间中一次只能聚焦一个焦平面,深度天然就是注意力分配器。

也就是说,Z 轴不再是渲染参数,而是一种信息组织手段。这是范式变革里最需要先扭转的一点:平面设计里的"上/下、左/右"对应的是阅读顺序,空间设计里的"近/远"对应的是认知优先级。

同一张卡片,2D 和空间两种写法

下面用一个商品卡片做对照。2D 版本是常见的平铺卡片;空间版本把同一张卡片放进一个有纵深的 Stack 里,用perspective和z位移拉开层次。

import{curves}from'@kit.ArkUI';@Entry@Componentstruct CardParadigmDemo{@Stateprivatespatial:boolean=false;@BuilderProductCard(title:string,price:string){Column({space:6}){// 占位图,实际项目替换为 ImageRow().width('100%').aspectRatio(1).backgroundColor('#E8EDF5').borderRadius(12)Text(title).fontSize(15).fontWeight(FontWeight.Medium).maxLines(1)Text(price).fontSize(13).fontColor('#E85D3D')}.padding(10).width(150).backgroundColor(Color.White).borderRadius(16).shadow({radius:12,color:'#14000000',offsetY:4})}build(){Column(){// Stack 是空间感的起点:子组件在这里共享同一块画布Stack({alignContent:Alignment.Center}){this.ProductCard('旧旅行箱','¥429').zIndex(0).translate({x:this.spatial?-70:-50,y:0,z:this.spatial?-60:0}).rotate({x:0,y:1,angle:this.spatial?-18:0,perspective:900}).opacity(this.spatial?0.75:1)this.ProductCard('主推商品','¥199').zIndex(2).translate({x:0,y:this.spatial?6:0,z:this.spatial?20:0}).rotate({x:0,y:1,angle:this.spatial?-4:0,perspective:900}).scale({x:this.spatial?1.12:1,y:this.spatial?1.12:1})this.ProductCard('新款上市','¥359').zIndex(1).translate({x:this.spatial?70:50,y:0,z:this.spatial?-60:0}).rotate({x:0,y:1,angle:this.spatial?16:0,perspective:900}).opacity(this.spatial?0.75:1)}.width('100%').height(320)Button(this.spatial?'回到平面':'进入空间').margin({top:24}).onClick(()=>{// 一次性把三张卡片的位移/旋转/缩放补间到目标状态this.getUIContext()?.animateTo({duration:400,curve:curves.springMotion(0.8,20)},()=>{this.spatial=!this.spatial;});})}.width('100%').height('100%').justifyContent(FlexAlign.Center)}}

这段代码里,spatial这个布尔量切换的不是"有没有动画",而是三张卡片在 Z 轴上的相对关系:主推商品被拉到z: 20并放大,两侧商品退到z: -60并降低不透明度。perspective: 900提供视距——值越小透视越夸张,值越大越接近正交投影。想深入的话,perspective和centerZ组合还能做出"绕自己所在平面翻转"的效果。

这个例子里,真正决定信息层级的不是颜色也不是字号,而是 z 位置的相对排序。这就是空间 UI 和 2D UI 最本质的区别。

2D UI 与空间 UI 的设计要素对照

把设计要素拆开看,差异更直观:

设计要素2D 平面 UI空间 UI变化实质
信息呈现靠网格、留白、分区组织,信息量受单屏面积限制靠距离、遮挡、景深组织,信息可分层堆叠在纵深上从"平面排布"变成"纵深编排"
导航固定坐标系,页面跳转即视角切换视角本身可移动,导航可以是"走过去"或"拉近看"从"切换页面"变成"移动观察点"
反馈颜色变化、缩放、位移,幅度小且以像素为单位可叠加深度弹出、材质高光、空间音效、轻微透视偏移反馈通道从 1 个扩到 3 个以上
状态选中/禁用/加载用样式区分除样式外,还需区分"在视野内/外"“可触及/过远”状态维度与用户姿态相关
层级zIndex只决定绘制顺序Z 位置决定真实远近,参与遮挡与透视层级从"视觉排序"变成"空间事实"
交互输入点击、滑动、长按(触点即目标)视线、手势、头部姿态协同,目标需要"选中"过程输入从"直接点"变成"先瞄准再动作"

这张表里最容易被低估的是最后两列。层级和交互输入这两栏,直接决定了 2D 那套"所见即所点"的直觉不能照搬。

案例:设置中心从列表变成分层空间

拿最常见的设置中心举例。2D 版本是一列设置项,用户滚动、点进去、返回。空间化之后,可以让"一级入口"作为前景层平铺,"二级详情"沉到中景,环境/预览作为背景层。

2D 路径

空间路径

用户进入设置中心

选择导航方式

滚动列表

点击条目

页面跳转 push 详情页

返回 pop 回列表

视线/手势选中前台卡片

卡片沿 Z 轴前移并放大

二级详情在背景层淡入

手势后推 = 返回上一层

卡片回落到原始 z 位置

两条路径的差别不只是动效。2D 路径里,返回是"撤销一次操作";空间路径里,返回是"退后一步"。后者更接近人在物理空间里的直觉,代价是用户必须始终知道自己在哪一层——这正是设计门槛,系统替不了你。

再往前一步,如果这个设置中心接入 3DGS 场景(比如相机类 App 让用户在实景空间里调整参数),设置项就不再是列表,而是悬浮在环境里的锚点。Spatial Recon Kit 加载 3DGS 模型后,配合 ArkGraphics 3D 的相机和光源,锚点会随视角变化产生合理的透视关系。这类场景里,设置项的空间位置本身就是语义:贴近实物的参数(比如滤镜强度)就该靠近那件实物。

几条小经验

  • 先问"Z 轴在这个页面承担什么职责",再动手写代码。如果答案只是"好看",大概率不该上 3D。
  • 把深度当层级用,别当装饰用。让用户在纵深里找到方向,比让元素飘起来更有价值。
  • 2D 到 3D 的第一步通常是"分层的 Stack",不是"加载一个 3D 模型"。绝大多数页面用层叠 + 透视就够了。
  • 透视值(perspective)要统一。同屏元素用不同视距,会让人眼判断不了它们的远近关系。
  • 动效时间控制在 300~500ms。空间位移过大又太慢,比平面动画更容易引发不适。

注意一下下哦

  • 把zIndex当成 Z 轴。zIndex只影响绘制顺序,不产生透视和遮挡的物理感。要真实纵深,得用translate的z配合perspective。
  • rotate和scale的锚点打架。两个属性都设centerX/centerY时,以属性链里后设置的为准。写链式调用时别想当然。
  • 透视中心默认在组件自身。做整屏空间感时,往往需要把旋转锚点对齐到屏幕中心或观察者位置,否则所有元素各转各的。
  • 忽略可触及范围。平面里屏幕边缘还能点,空间里"远处"的控件既难点中也不该高频使用。
  • 只做视觉不做状态。元素进出视野、被遮挡、过远这些状态如果没设计,用户会以为自己操作失败了。

空间计算的门槛,一半在"怎么写",另一半在"为什么这么写"。系统把前一半按低了,后一半还得靠自己。
#鸿蒙 #HarmonyOS 7(API 26)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询