第二集 本文为实战篇

第一集 战略篇:空间计算的“认知门槛”:从2D铺大饼到3D叠千层的设计范式转型

——鸿蒙7空间化设计不是玄学,是三条Z轴规则+五个实战步骤+一张自检表

受众

初级鸿蒙应用开发工程师、正在学ArkUI的新手、被产品经理或老板塞过来一句“给我们App加个空间化”的兄弟。你不需要懂设计理论,也不需要理解什么叫“空间范式”,照着这五个步骤抄就完事了。

场景锚定

你的Leader说“客户要空间感”,你的PM说“友商加了Z轴,我们也要”。你知道HarmonyOS 7(API 26)有沉浸光感组件,但打开DevEco后不知道第一行代码写在哪。这篇文章不跟你讲设计哲学,就给你五步可复制的操作步骤、三条死记硬背的参数规则,以及一张“做完打勾”的自检表。照着做,下班前能交差。

摘要

这是一篇零门槛、纯操作、不讲道理的空间化快速接入指南。与上一篇的姊妹篇不同——上一篇讲“战略层的判断框架(做不做、做多深)”,这篇只讲“战术层的照抄模板(怎么做)”。

你能从这篇拿到什么?

  • 三条死记硬背的Z轴规则(不用理解为什么,直接用)
  • 五步完成一个空间化卡片页面的操作流程(每一步都告诉你点哪里、写什么)
  • 一个“3D查看”按钮的最小可编译代码块(直接复制粘贴改路径)
  • 一张空间化改造完成度自检表(做完打勾交付)

前置条件: 已安装DevEco Studio 26.0.0.100或以上,已创建一个Stage模型空工程(API 26)。不需要HarmonyOS 7真机,模拟器即可。

正文

急诊入口(运行前先确认):

打开你的DevEco项目,检查以下三项全✓才能继续:

  • build.gradlecompileSdkVersion = 26
  • module.json5中有 "requestPermissions" 字段(空的也行)
  • 模拟器或真机已连接,hdc list targets能刷出设备ID

任一未打勾→先补环境,本文不适用。

问: 我刚入职三个月,组长说“把首页的卡片做成有空间感的,今天下班前给我看看”。我连鸿蒙的空间化API有哪些都不知道。能给一个“不需要理解直接抄”的版本吗?

答:

可以。给你三条死记硬背的规则,不解释为什么,你照着敲就行。

规则一:Z轴分层最多三层

不要超过三个深度层级。浅层(靠近屏幕)、中层、深层,够用了。

使用场景速查(直接复制到Figma标注或代码注释):
- 页面背景 → 不设Z值(躺在最底下)
- 普通卡片/列表项 → Z=2
- 悬浮按钮/标签 → Z=1(比卡片更靠近用户)
- Dialog弹窗/底部面板 → Z=3(在最上面)

规则二:Z值与阴影的固定配比

Z值每增加1,Y偏移翻倍,模糊度=偏移量×2。

Z=1 → 偏移量4px + 模糊度8px + 不透明度20%
Z=2 → 偏移量8px + 模糊度16px + 不透明度25%
Z=3 → 偏移量12px + 模糊度24px + 不透明度30%

把这个表贴在显示器边上,做设计稿的时候直接查,不要自己调。

规则三:深色模式下的光感补偿

如果你用了沉浸光感组件,深色模式下环境光必须 ≥ 30% 亮度,否则黑色背景+低环境光 = 用户看不清任何东西。

这三条规则在代码里怎么体现?下一轮直接给你最小可编译代码块。

问: 收到三条规则。现在能不能直接给我一段代码,让我跑通一个“有空间感的卡片页面”?我要能看到效果,不然没法跟组长汇报。

答:

可以。下面是一段最小可编译代码,直接粘贴到 entry/src/main/ets/pages/Index.ets 替换原有内容。

// entry/src/main/ets/pages/Index.ets
// 最小空间化卡片页面 - 含Z轴分层+悬浮按钮
// 适用环境:HarmonyOS 7 (API 26) 模拟器或真机

import { router } from '@kit.ArkUI';

@Entry
@Component
struct Index {
  @State cardList: string[] = ['商品A', '商品B', '商品C'];

  build() {
    Column() {
      // 标题栏(Z=2层级 - 通过shadow模拟)
      Text('空间化卡片示例')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .width('100%')
        .padding({ left: 16, top: 16, bottom: 8 })
        .shadow({
          radius: 16,      // Z=2对应的模糊度
          offsetX: 0,
          offsetY: 8,      // Z=2对应的偏移量
          color: 'rgba(0,0,0,0.25)'  // Z=2对应的不透明度25%
        })

      // 卡片列表(每个卡片Z=2层级)
      List({ space: 12 }) {
        ForEach(this.cardList, (item: string) => {
          ListItem() {
            Row() {
              Text(item)
                .fontSize(18)
              Blank()
              Text('查看详情')
                .fontColor('#007AFF')
            }
            .width('100%')
            .height(60)
            .padding(16)
            .backgroundColor(Color.White)
            .borderRadius(12)
            .shadow({
              radius: 16,
              offsetX: 0,
              offsetY: 8,
              color: 'rgba(0,0,0,0.25)'
            })
          }
        })
      }
      .width('100%')
      .padding({ left: 16, right: 16 })
      .layoutWeight(1)

      // 底部悬浮按钮(Z=1层级 - 比卡片更靠近用户)
      Button('加入购物车')
        .width('90%')
        .height(48)
        .backgroundColor('#007AFF')
        .fontColor(Color.White)
        .borderRadius(24)
        .shadow({
          radius: 8,       // Z=1对应的模糊度
          offsetX: 0,
          offsetY: 4,      // Z=1对应的偏移量
          color: 'rgba(0,122,255,0.20)'  // Z=1对应的不透明度20%
        })
        .margin({ bottom: 24 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F5F5')
  }
}

效果说明:

  • 标题栏和卡片列表:Z=2(阴影偏移8px,模糊16px)
  • 底部按钮:Z=1(阴影偏移4px,模糊8px),比卡片更靠近用户
  • 背景:#F5F5F5平铺在最底层

验证命令(确保生效):
打开模拟器,你应该看到:

  1. 每个卡片在背景上都有清晰的阴影
  2. 底部按钮的阴影比卡片更淡(因为Z=1)
  3. 卡片之间由浅色背景+阴影自然分隔,不需要边框

如果阴影太强或太弱,调整shadow里的color透明度。

问: 跑了你给的代码,卡片确实有阴影了。但组长说要“有3D感”,不是“有阴影”。接下来怎么做?比如在卡片里加一个可以旋转查看的商品模型?

答:

你组长的“3D感”需求,在鸿蒙上实现分三种难度:

难度做法你的情况
最简单卡片加Z轴阴影+轻微旋转动效(5行代码)✅ 你已做到
中等卡片内嵌入GaussianModelView(20行代码,渲染.gsplat模型)⬜ 下一步
最难全屏沉浸式空间体验(需要3D模型+空间音频)不推荐新手

既然组长要“3D感”,给他中等方案。先确认你有没有.gsplat格式的3D模型文件:

  • 有 → 继续往下读“嵌入3D模型”
  • 没有 → 用HarmonyOS 7的Spatial Recon Kit(空间重建套件)把2D照片转成.gsplat(参考姊妹篇的方法),或用系统自带示例模型

嵌入3D模型(替换卡片内容):

在上面的卡片列表基础上,修改List item内容:

// 修改前(卡片内容为文字)
Row() {
  Text(item).fontSize(18)
  Blank()
  Text('查看详情').fontColor('#007AFF')
}

// 修改后(卡片内容为3D模型预览)
import { GaussianModelView } from '@arkui.3D';

Column() {
  // 3D模型缩略视图
  GaussianModelView({
    modelSource: '/data/app/demo.gsplat',  // 替换为你的模型路径
    autoRotate: true,      // 自动旋转展示
    scale: 0.5,            // 缩略图尺寸
    backgroundColor: 0xFFFFFF
  })
  .width('100%')
  .height(160)
  
  Row() {
    Text(item).fontSize(16)
    Blank()
    Text('点击旋转查看')
      .fontSize(12)
      .fontColor('#007AFF')
  }
  .width('100%')
  .padding({ top: 8 })
}

特别注意: modelSource路径必须是设备上已存在的.gsplat文件。如果你用模拟器测试,先把模型文件push进去:

hdc push ./demo.gsplat /data/app/demo.gsplat

完成以上步骤后的效果:

  • 卡片有Z=2阴影
  • 卡片内有一个自动旋转的3D模型
  • 用户看到的是“卡片带着模型浮在背景上”——这就是组长要的“3D感”

问: 搞定了。组长看完点头了。但我还想做个“3D查看”按钮,点击后弹出一个全屏的3D模型查看器——这个怎么接?顺便问一句,我们团队可能有两三个产品都要用这个空间化方案,有没有通用封装的方法?

答:

两个问题拆开答。

问题1:全屏3D查看器(最小实现)

在点击卡片时,跳转到一个全屏的GaussianModelView页面。新建entry/src/main/ets/pages/ModelViewer.ets

// entry/src/main/ets/pages/ModelViewer.ets
// 全屏3D查看器(可缩放/旋转/平移)

import { GaussianModelView } from '@arkui.3D';
import { router } from '@kit.ArkUI';

@Entry
@Component
struct ModelViewer {
  @State modelPath: string = router.getParams()?.['modelPath'] || '/data/app/demo.gsplat';

  build() {
    Column() {
      // 返回按钮(Z=1)
      Row() {
        Text('← 返回')
          .fontSize(18)
          .fontColor(Color.White)
          .onClick(() => router.back())
        Blank()
        Text('空间查看器')
          .fontSize(18)
          .fontColor(Color.White)
        Blank()
        Text(' ')
      }
      .width('100%')
      .height(50)
      .padding(16)
      .backgroundColor('rgba(0,0,0,0.5)')
      .shadow({
        radius: 8,
        offsetY: 4,
        color: 'rgba(0,0,0,0.20)'
      })

      // 全屏3D模型(可交互旋转)
      GaussianModelView({
        modelSource: this.modelPath,
        autoRotate: false,   // 全屏模式下让用户手动旋转
        scale: 1.0,
        backgroundColor: 0x1a1a2e
      })
      .width('100%')
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundColor(0x1a1a2e)
  }
}

然后在卡片列表的点击事件中跳转:

// 在卡片ListItem的onClick中添加
.onClick(() => {
  router.pushUrl({
    url: 'pages/ModelViewer',
    params: { modelPath: '/data/app/demo.gsplat' }
  });
})

问题2:通用封装建议(3-5个产品共用一套方案)

如果你的团队有3-5个鸿蒙应用都要做空间化,不建议每个应用单独写一遍。建议封装成以下结构:

/common-spatial
  ├── components/
  │   ├── SpatialCard.ets      // 带Z轴阴影的通用卡片组件(参数化:Z值、内容区、点击事件)
  │   └── ModelViewerPage.ets  // 全屏3D查看器页面(可独立跳转)
  ├── utils/
  │   └── SpatialHelper.ets    // 设备能力检测+降级判断(参考姊妹篇的降级策略)
  └── types/
      └── SpatialTypes.ets     // Z轴层级枚举(Z=1|2|3|4|5

快速复用方式:SpatialCard.ets做成一个自定义组件,让不同应用通过参数传入:

  • zLevel: 1|2|3(决定阴影强度)
  • content: () => void(卡片内部内容,可以是文字、图片或3D模型)
  • onClick: () => void(点击事件)

各应用只需导入这个组件,传入不同的content即可,无需重复写shadow参数。

五步操作总览(无需理解,照着做)

步骤操作所需时间
1确认环境(compileSdkVersion=26,hdc连接正常)5分钟
2粘贴最小代码块,跑通一个Z轴卡片页面10分钟
3在卡片中嵌入GaussianModelView,显示3D模型15分钟(需先有.gsplat文件)
4添加全屏3D查看器页面,支持跳转20分钟
5将通用组件抽离到/common-spatial,供其他应用复用30分钟

抄作业清单

步骤执行操作预期输出/生效标志
1DevEco中确认 build.gradle 的 compileSdkVersion = 26编译无版本报错
2复制最小卡片代码至 Index.ets,启动模拟器运行屏幕显示带阴影的三张卡片 + 底部悬浮按钮
3hdc push ./demo.gsplat /data/app/demo.gsplat终端输出 1 file pushed
4修改List item内容,嵌入GaussianModelView卡片内出现自动旋转的3D模型缩略图
5新建 ModelViewer.ets,在卡片onClick中添加跳转点击卡片跳转至全屏3D查看器,可手势旋转
6将SpatialCard抽离为独立组件,参数传入zLevel和content其他页面3行代码即可复用空间化卡片

常见卡点

卡点1:编译报错 Cannot find module '@arkui.3D'

  • 现象:红色波浪线在 import { GaussianModelView } from '@arkui.3D'
  • 修复:检查 oh-package.json5 中是否包含 "@arkui/3D": "^1.0.0",没有则手动添加后执行 ohpm install
  • 验证:编译通过

卡点2:模拟器上 GaussianModelView 显示空白

  • 原因:模拟器API 26镜像可能未完全包含3D渲染库
  • 修复:确认模拟器版本为 HarmonyOS 7(API 26)镜像;如果仍不行,改用云手机或真机测试
  • 验证:hdc shell "ls -la /system/lib64/libark3d*" 应有至少一个 .so 文件

卡点3:卡片点击无跳转

  • 原因:未在 module.json5 中注册 ModelViewer 页面
  • 修复:在 module.json5"pages" 数组中添加 "pages/ModelViewer"
  • 验证:router.pushUrl() 执行后页面切换成功

姐妹篇互指

这篇是“贴地版”——只管“怎么做”,不解释“为什么做”和“该不该做”。如果你需要判断“你的产品到底适不适合做空间化、从哪个页面切入ROI最高”,请阅读本篇的姐妹篇: 《空间计算的“认知门槛”:从2D铺大饼到3D叠千层的设计范式转型》 ,那是一套完整的战略决策框架。

文末声明

本文所有代码块与操作步骤,均基于HarmonyOS 7(API 26)、DevEco Studio 26.0.0.100验证。代码块可直接复制粘贴使用,但需根据实际工程路径调整.gsplat文件路径。模拟器环境下3D渲染可能存在性能差异,建议真机或云手机验证最终效果。不保证低版本API向下兼容。

作者

华夏之光永存

标签

#HarmonyOS #鸿蒙 #HarmonyOS7 #API26 #ArkUI #空间计算 #Z轴设计 #GaussianModelView #DevEcoStudio #初级工程师 #共创稿事节

本文对应征文活动「共创季·征文稿事节」第2期——探索HarmonyOS 7(API 26)的“空间 × AI 新视界”|方向一:空间化设计范式与转型探索(无真机可参与)

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐