尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

HarmonyOS应用《玄象》开发实战:SplashPage 全屏暗色背景与 Stack 层叠布局

HarmonyOS应用《玄象》开发实战:SplashPage 全屏暗色背景与 Stack 层叠布局
📅 发布时间:2026/7/26 21:05:36

阅读时长:约 18 分钟 | 难度:★★★★☆ | 篇章:第 2 篇 · 启动体验:Splash 与动画 对应源码:entry/src/main/ets/pages/SplashPage.ets、entry/src/main/ets/pages/Index.ets

前言

启动页是用户对应用的第一印象。玄象项目作为一款中华传统文化主题应用,启动页采用深邃星空 + 金色太极的视觉语言,传递出“玄之又玄,众妙之门“的东方美学。本篇将深入剖析玄象项目SplashPage的实现细节:从@State状态定义、Stack层叠布局、Canvas多实例管理,到aboutToAppear生命周期与setTimeout跳转。掌握这些技术细节,您就能为任何 HarmonyOS 应用打造令人印象深刻的启动体验。

提示:启动页的设计精髓在于“瞬间传达品牌调性“。玄象项目用 3 秒钟让用户感受到东方神秘主义与金色质感,这一视觉锚点将贯穿整个应用。

一、SplashPage 完整源码

1.1 源码全貌

import { Colors } from '../common/constants/Colors'; import { router } from '@kit.ArkUI'; @Entry @Component export struct SplashPage { @State fadeOpacity: number = 0; @State logoScale: number = 0.8; private timer: number = -1; private settings: RenderingContextSettings = new RenderingContextSettings(true); private starFieldContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private starMapContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private taijiContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); aboutToAppear(): void { this.fadeOpacity = 0; this.logoScale = 0.8; setTimeout(() => { this.fadeOpacity = 1; this.logoScale = 1; }, 100); this.timer = setTimeout(() => { router.replaceUrl({ url: 'pages/HomePage' }); }, 3000); } aboutToDisappear(): void { if (this.timer !== -1) { clearTimeout(this.timer); } } build() { Stack() { // 星空背景 Canvas(this.starFieldContext) .width('100%') .height('100%') .onReady(() => { this.drawStarField(this.starFieldContext, this.starFieldContext.width, this.starFieldContext.height); }) // 底部星图装饰 Canvas(this.starMapContext) .width('100%') .height('40%') .align(Alignment.Bottom) .onReady(() => { this.drawStarMap(this.starMapContext, this.starMapContext.width, this.starMapContext.height); }) // 中央内容 Column({ space: 20 }) { Canvas(this.taijiContext) .width(220) .height(220) .margin({ top: 100 }) .onReady(() => { this.drawTaiji(this.taijiContext, this.taijiContext.width, this.taijiContext.height); }) Column({ space: 12 }) { Text('玄象') .fontSize(56) .fontWeight(FontWeight.Bold) .fontColor(Colors.PRIMARY_GOLD) .letterSpacing(8) Text('中华传统文化') .fontSize(20) .fontColor(Colors.LIGHT_GOLD) .letterSpacing(4) } } .width('100%') .height('100%') .opacity(this.fadeOpacity) .scale({ x: this.logoScale, y: this.logoScale }) .animation({ duration: 1000, curve: Curve.EaseOut }) } .width('100%') .height('100%') .backgroundColor(Colors.BG_DARK) } private drawStarField = (canvas: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number) => { // ... } private drawTaiji = (canvas: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number) => { // ... } private drawStarMap = (canvas: CanvasRenderingContext2D, canvasWidth: number, canvasHeight: number) => { // ... } }

1.2 源码结构拆解

玄象项目SplashPage.ets包含四大组成部分:

部分行数职责
状态与上下文定义8 行@State与CanvasRenderingContext2D
生命周期回调18 行aboutToAppear/aboutToDisappear
build渲染方法60 行Stack+ 3 个Canvas+ 中央文字
Canvas 绘制函数100+ 行星空 / 太极 / 星图

二、@State 状态变量

2.1 状态变量定义

@State fadeOpacity: number = 0; @State logoScale: number = 0.8;

玄象项目使用两个@State变量控制启动页动画:

状态变量初始值作用
fadeOpacity0中央内容的透明度
logoScale0.8中央内容的缩放比例

2.2 @State 工作原理

@State是 ArkUI 的响应式状态装饰器,当变量值改变时,引用该变量的 UI 组件会自动重新渲染:

@State fadeOpacity = 0 ↓ [UI 渲染] opacity(0) ↓ [setTimeout 100ms 后] fadeOpacity = 1 ↓ [ArkUI 监听到变化] ↓ [重新渲染] opacity(1) + 动画过渡

2.3 状态变量的初始化时机

玄象项目的状态变量初始化发生在组件实例创建时:

@State fadeOpacity: number = 0; // 实例化时初始化为 0

但在aboutToAppear中又重新赋值:

aboutToAppear(): void { this.fadeOpacity = 0; // 重置为 0 this.logoScale = 0.8; // 重置为 0.8 // ... }

提示:这种“双重保险“的写法确保每次进入启动页时状态都是从初始值开始的。即便应用被系统回收后重建,动画也能正确播放。

三、timer 与生命周期管理

3.1 timer 变量定义

private timer: number = -1;

玄象项目使用private timer保存setTimeout返回的 timer id,初始值-1表示“无 timer“。

3.2 aboutToAppear 中启动两个 timer

aboutToAppear(): void { this.fadeOpacity = 0; this.logoScale = 0.8; // timer 1:100ms 后开始淡入动画 setTimeout(() => { this.fadeOpacity = 1; this.logoScale = 1; }, 100); // timer 2:3000ms 后跳转首页 this.timer = setTimeout(() => { router.replaceUrl({ url: 'pages/HomePage' }); }, 3000); }

玄象项目在aboutToAppear中启动两个定时器:

  1. 淡入动画定时器:100ms 后将透明度从 0 改为 1,触发淡入动画。
  2. 跳转定时器:3000ms 后调用router.replaceUrl跳转到首页。

3.3 aboutToDisappear 中清理 timer

aboutToDisappear(): void { if (this.timer !== -1) { clearTimeout(this.timer); } }

玄象项目在aboutToDisappear中清理 timer,避免组件销毁后定时器仍触发。

3.4 两个 timer 的差异

timer用途是否需要清理
淡入动画 timer触发一次性状态变更不需要(执行完自动销毁)
跳转 timer3 秒后跳转需要(避免重复跳转)

提示:玄象项目仅保存了第二个 timer 的 id,因为只有这个 timer 在组件销毁时可能还未执行。第一个 timer 在 100ms 内必然执行完毕,无需保存 id。

四、Stack 层叠布局

4.1 Stack 容器特性

Stack是 ArkUI 提供的层叠布局容器,子元素按顺序堆叠:

  • 后声明的子元素在上方
  • 默认居中对齐
  • 可通过.align()修改对齐方式

4.2 SplashPage 的 Stack 结构

Stack() { // 第一层:星空背景(最底层,占满全屏) Canvas(this.starFieldContext) .width('100%') .height('100%') // 第二层:底部星图装饰(中间层,对齐底部,占下方 40%) Canvas(this.starMapContext) .width('100%') .height('40%') .align(Alignment.Bottom) // 第三层:中央内容(最上层,太极图 + 文字) Column({ space: 20 }) { // ... } .width('100%') .height('100%') } .width('100%') .height('100%') .backgroundColor(Colors.BG_DARK)

4.3 三层视觉关系图

┌──────────────────────────────────────┐ │ │ │ [星空背景 Canvas] │ ← 第一层(最底) │ [底部星图 Canvas] │ ← 第二层(中间) │ │ │ [太极 Canvas] │ ← 第三层(最上) │ [玄象 标题] │ │ [中华传统文化] │ │ │ └──────────────────────────────────────┘

4.4 Stack 的关键配置

玄象项目Stack的关键配置:

配置值作用
width'100%'占满屏幕宽度
height'100%'占满屏幕高度
backgroundColorColors.BG_DARK深色背景(避免首帧白屏)

提示:.backgroundColor(Colors.BG_DARK)是玄象项目启动页的关键技巧。它确保即 Canvas 还未完成绘制,用户看到的也是深色背景而非刺眼的白色。

五、Canvas 多实例管理

5.1 三个 CanvasRenderingContext2D 实例

private settings: RenderingContextSettings = new RenderingContextSettings(true); private starFieldContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private starMapContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings); private taijiContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

玄象项目创建了 3 个CanvasRenderingContext2D实例,分别对应星空、星图、太极。

5.2 共享 RenderingContextSettings

三个 Context 共享同一个RenderingContextSettings:

private settings: RenderingContextSettings = new RenderingContextSettings(true);

RenderingContextSettings(true)启用抗锯齿,让 Canvas 绘制的圆形与曲线更平滑。

5.3 为什么使用多个 Context

玄象项目使用多个Canvas实例的原因:

  1. 隔离绘制状态:每个 Context 独立管理fillStyle/strokeStyle等状态,避免相互污染。
  2. 独立尺寸控制:星空背景占 100%,星图占 40%,太极占 220×220,每个 Canvas 尺寸独立。
  3. 独立对齐方式:星图通过.align(Alignment.Bottom)对齐底部,其他 Canvas 居中。

5.4 Canvas onReady 时机

Canvas(this.starFieldContext) .width('100%') .height('100%') .onReady(() => { this.drawStarField(this.starFieldContext, this.starFieldContext.width, this.starFieldContext.height); })

onReady在 Canvas 准备好绘制时触发,此时starFieldContext.width与height已经是实际像素值,可以安全绘制。

提示:玄象项目在onReady内立即调用绘制函数,确保 Canvas 一准备好就开始绘制。如果在aboutToAppear中绘制,Canvas 可能还未准备好,导致绘制失败。

六、中央内容布局

6.1 Column 容器结构

Column({ space: 20 }) { // 太极图 Canvas(this.taijiContext) .width(220) .height(220) .margin({ top: 100 }) // 标题列 Column({ space: 12 }) { Text('玄象') .fontSize(56) .fontWeight(FontWeight.Bold) .fontColor(Colors.PRIMARY_GOLD) .letterSpacing(8) Text('中华传统文化') .fontSize(20) .fontColor(Colors.LIGHT_GOLD) .letterSpacing(4) } } .width('100%') .height('100%') .opacity(this.fadeOpacity) .scale({ x: this.logoScale, y: this.logoScale }) .animation({ duration: 1000, curve: Curve.EaseOut })

6.2 嵌套 Column 的设计考量

玄象项目使用嵌套Column的设计:

Column (中央内容容器,space=20) ├── Canvas (太极图) └── Column (标题列,space=12) ├── Text "玄象" └── Text "中华传统文化"

为什么不直接使用单个 Column?

  • 外层Column的space=20控制太极图与标题列之间的间距。
  • 内层Column的space=12控制主标题与副标题之间的间距。
  • 不同的间距通过嵌套实现独立控制。

6.3 字体属性详解

玄象项目主标题“玄象“的字体属性:

属性值作用
fontSize56主标题字号
fontWeightFontWeight.Bold加粗显示
fontColorColors.PRIMARY_GOLD主金色
letterSpacing8字间距 8vp

副标题“中华传统文化“的字体属性:

属性值作用
fontSize20副标题字号
fontColorColors.LIGHT_GOLD浅金色
letterSpacing4字间距 4vp

提示:letterSpacing是营造东方书法美感的关键属性。玄象项目通过字间距拉开,让文字显得更“舒展“。

七、淡入动画机制

7.1 opacity 与 scale 双重动画

.opacity(this.fadeOpacity) .scale({ x: this.logoScale, y: this.logoScale }) .animation({ duration: 1000, curve: Curve.EaseOut })

玄象项目启动页中央内容有两层动画:

  1. opacity 透明度动画:从 0 渐变到 1,营造“浮现“效果。
  2. scale 缩放动画:从 0.8 渐变到 1,营造“由小到大“效果。

7.2 animation 关键参数

.animation({ duration: 1000, curve: Curve.EaseOut })
参数值作用
duration1000ms动画时长
curveCurve.EaseOut缓动曲线,先快后慢

7.3 EaseOut 曲线的视觉感受

Curve.EaseOut的运动曲线:

速度 ↑ │ ╱────╲ │ ╱ ╲ │╱ ╲___ └─────────────→ 时间

EaseOut的特点:

  • 开始快:动画一开始就有较大变化。
  • 结束慢:接近终点时变化放缓。

这种曲线特别适合“元素出现“的场景,让用户感受到有力道的浮现。

7.4 动画触发时机

aboutToAppear(): void { this.fadeOpacity = 0; this.logoScale = 0.8; setTimeout(() => { this.fadeOpacity = 1; // 状态改变触发动画 this.logoScale = 1; }, 100); }

玄象项目刻意延迟 100ms 才改变状态,目的:

  1. 确保组件已渲染:等待 ArkUI 完成首次渲染。
  2. 避免状态丢失:如果状态在渲染前就改变,可能导致动画丢失。

提示:这种“延迟 100ms 触发动画“是 ArkUI 中常见的最佳实践。也可以使用setTimeout(..., 0)让状态变更进入下一个事件循环。

八、Stack 布局的进阶技巧

8.1 使用 align 控制子元素位置

Canvas(this.starMapContext) .width('100%') .height('40%') .align(Alignment.Bottom) // 对齐底部

Stack的align属性控制子元素在 Stack 中的对齐方式:

对齐方式含义
Alignment.TopStart左上角
Alignment.Top顶部居中
Alignment.Center居中(默认)
Alignment.Bottom底部居中
Alignment.BottomEnd右下角

8.2 使用 position 精确定位

玄象项目在首页“今日天地“卡片中使用position实现五行环绕:

.position(this.getFiveElementPosition(index, 180, 44))

position接收一个Position对象{ x, y },精确控制子元素的左上角位置。

8.3 使用 zIndex 控制层级

如果需要手动控制子元素的堆叠层级,可以使用zIndex:

Canvas(this.starFieldContext) .zIndex(1) // 最底层 Canvas(this.starMapContext) .zIndex(2) // 中间层 Column({ space: 20 }) { // 中央内容 } .zIndex(3) // 最上层

提示:玄象项目通过Stack中子元素的声明顺序控制层级(后声明的在上层),因此不需要显式使用zIndex。

九、SplashPage 的扩展方向

9.1 添加品牌 LOGO 图片

玄象项目当前使用 Canvas 绘制太极图。如果引入 LOGO 图片:

Column({ space: 20 }) { Image($r('app.media.logo')) .width(220) .height(220) .objectFit(ImageFit.Contain) .margin({ top: 100 }) Column({ space: 12 }) { // 文字 } }

9.2 添加加载进度条

启动页常用于显示加载进度:

Column({ space: 20 }) { // 太极图 + 标题 // 加载进度条 Progress({ value: this.loadingProgress, total: 100, type: ProgressType.Linear }) .width('60%') .color(Colors.PRIMARY_GOLD) }

9.3 添加版本号

Column({ space: 20 }) { // 主内容 } .justifyContent(FlexAlign.Center) Text(`v1.0.0`) .fontSize(12) .fontColor(Colors.TEXT_DIM) .position({ x: '50%', y: '90%' }) .translate({ x: '-50%' })

总结

本篇以玄象项目SplashPage为蓝本,深入剖析了 HarmonyOS 应用启动页的实现细节:从@State响应式状态定义、Stack三层视觉堆叠、Canvas多实例管理,到aboutToAppear生命周期、setTimeout双定时器机制、opacity + scale双重动画,再到backgroundColor预设避免首帧白屏的关键技巧。掌握这套启动页实现方法论,您就能为任何 HarmonyOS 应用打造令人印象深刻的启动体验。

下一篇:《12 · Canvas 星空绘制:arc / fillStyle / 随机散点算法》,将带您深入玄象项目启动页的星空背景 Canvas 绘制细节。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • HarmonyOS 官方文档:Stack 组件
  • HarmonyOS 官方文档:Canvas 组件
  • HarmonyOS 官方文档:CanvasRenderingContext2D
  • HarmonyOS 官方文档:animation 动画
  • 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关新闻

  • 5分钟掌握BilibiliDown:一站式B站视频下载与批量处理终极指南
  • 大模型预训练全流程技术解析与实战优化
  • 腾讯开源AI作曲神器:三步上手专业级歌曲生成完整指南

最新新闻

  • 杭州耀红火灯饰科技有限公司品牌档案 - 资讯报道
  • RSA数字签名原理与实战:从私钥加密到公钥验证的完整指南
  • spaCy与LLM在NLP任务中的高效集成实践
  • 基于JavaWeb的美食交流宣传系统的设计与实现开题报告
  • HarmonyOS应用《玄象》开发实战:九宫格功能入口:Grid / GridItem / columnsTemplate(‘1fr 1fr 1fr‘)
  • HarmonyOS应用《玄象》开发实战:CastDivinationPage 起卦页:六爻动变算法 + 18 次三变法模拟

日新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号