【OpenHarmony/HarmonyOs 】物理模型详情页模板:返回、收藏、安全区、动效与参数面板统一设计
【OpenHarmony/HarmonyOs 】物理模型详情页模板:返回、收藏、安全区、动效与参数面板统一设计
本文基于我的 OpenHarmony/HarmonyOS 项目「物理视界 PhysicsVision」整理。项目中 28 个物理模型虽然内容不同,但详情页结构很统一:顶部返回栏、收藏按钮、Canvas 实验区、播放控制、参数调节、数据面板和知识说明。
这一篇单独拆“模型详情页模板”,对应“全新视觉与交互体验”和“隐私友好的本地学习”的主题。📐
一、为什么需要统一的模型详情页模板?
物理模型很多,如果每个页面都用完全不同的布局,用户会很快迷路。
「物理视界」中有声音传播、自由落体、平抛运动、电场线、光的干涉、凸透镜成像等模型。它们的物理内容不同,但页面操作应该保持一致:
- 左上角返回;
- 右上角收藏;
- 中间 Canvas 实验区;
- 下方控制按钮;
- 参数滑块;
- 数据展示;
- 知识解释。
统一模板可以让用户学会一次操作,就能迁移到所有模型。
二、顶部栏:返回 + 标题 + 收藏
以「光的干涉」页面为例:
Row() {
Text('←')
.fontSize(28)
.fontWeight(FontWeight.Bolder)
.fontColor($r('app.color.text_primary'))
.onClick(() => router.back())
Text('光的干涉 🌈')
.fontSize(20)
.fontWeight(FontWeight.Bolder)
.fontColor($r('app.color.text_primary'))
.margin({ left: 16 })
Blank()
Text(this.isFav() ? '❤️' : '🤍')
.fontSize(22)
.onClick(() => { this.toggleFav() })
}
这段结构几乎在多个模型页面中复用:
- 返回按钮负责路由回退;
- 标题告诉用户当前模型;
- 收藏按钮记录学习重点。
这是一个很适合学习类 App 的详情页头部结构。
三、安全区适配:详情页也要沉浸但不遮挡
顶部栏统一使用:
.padding({ left: 20, right: 20, top: 48, bottom: 14 })
.backgroundColor($r('app.color.bg_card'))
.border({ width: { bottom: 2 }, color: $r('app.color.border_strong') })
.expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP])
这里的设计考虑是:
- 顶部内容不会贴状态栏;
- 背景延伸到安全区;
- 底部边框让顶部栏和内容区分开;
- 深色模式下也能保持层次。
详情页不像首页那样使用大面积渐变 Header,而是使用更稳的卡片色顶部栏,方便用户专注实验本身。
四、收藏逻辑:每个模型都有自己的 modelIndex
每个模型页面都有自己的索引:
private modelIndex: number = 11
@StorageLink('favorites') favStr: string = ''
判断是否收藏:
isFav(): boolean {
if (this.favStr.length === 0) return false
let parts: string[] = this.favStr.split(',')
for (let i = 0; i < parts.length; i++) {
if (parseInt(parts[i]) === this.modelIndex) return true
}
return false
}
收藏切换:
toggleFav(): void {
if (this.isFav()) {
let parts: string[] = this.favStr.split(',')
let np: string[] = []
for (let i = 0; i < parts.length; i++) {
if (parseInt(parts[i]) !== this.modelIndex) np.push(parts[i])
}
this.favStr = np.join(',')
} else {
this.favStr = this.favStr.length === 0 ? this.modelIndex.toString() : this.favStr + ',' + this.modelIndex.toString()
}
}
这套逻辑让模型详情页和收藏页打通。
用户在详情页收藏后,可以在收藏页按分类快速找回。
五、Canvas 实验区:所有模型的视觉核心
模型详情页的主体通常是 Canvas:
Canvas(this.ctx)
.width('100%')
.height(340)
.backgroundColor($r('app.color.bg_page'))
.border({ width: 2, color: $r('app.color.border_strong') })
.borderRadius(20)
.onReady(() => {
this.canvasReady = true
this.drawScene()
})
.scale({ x: this.animCanvas ? 1 : 0.85, y: this.animCanvas ? 1 : 0.85 })
.opacity(this.animCanvas ? 1 : 0)
这里有几个统一细节:
- 边框强化实验台感觉;
- 圆角让视觉更柔和;
onReady后绘制;- 入场时缩放和淡入。
对物理学习来说,Canvas 就是“实验台”。
六、参数面板:滑块连接公式和画面
在光学、电磁学、力学模型中,参数面板大量使用 Slider:
Text(`波长 λ: ${this.wavelength.toFixed(0)} nm`)
Slider({ value: this.wavelength, min: 380, max: 700, step: 10 })
.trackColor($r('app.color.slider_track'))
.selectedColor(this.getColorFromWavelength())
.onChange((v: number) => {
this.wavelength = v
if (this.canvasReady) this.drawScene()
})
这种交互非常适合物理学习:
- 参数变化看得见;
- 公式结果实时更新;
- Canvas 画面立即重绘;
- 学生能主动探索变量关系。
七、数据面板:把现象落回公式
模型详情页通常会有数据展示,例如光的干涉:
Text('条纹间距 Δy')
Text(`${this.getFringeSpacing().toFixed(2)} mm`)
Text('Δy = λL/d')
凸透镜成像中则展示像距、像高、成像类型:
this.imageDist = v
this.imageHeight = -v / u * this.objectHeight
if (u > 2 * f) this.imageType = '倒立缩小实像'
else if (Math.abs(u - 2 * f) < 1) this.imageType = '倒立等大实像'
else if (u > f) this.imageType = '倒立放大实像'
else this.imageType = '正立放大虚像'
可视化负责吸引注意,数据面板负责建立理解。
八、动画入场:让页面更有层次
详情页通常有多段入场动画:
setTimeout(() => {
animateTo({ duration: 600, curve: curves.springCurve(0, 1, 328, 28) }, () => {
this.animCanvas = true
})
}, 100)
setTimeout(() => {
animateTo({ duration: 600, curve: curves.springCurve(0, 1, 328, 28) }, () => {
this.animParams = true
})
}, 250)
Canvas、控制区、参数区、数据区分批出现。
这种节奏比所有内容瞬间出现更自然,也更符合“实验室”场景感。
九、本地优先:详情页不需要敏感权限
这些模型详情页都不需要:
- 相机权限;
- 相册权限;
- 网络请求;
- AI 识图;
- 定位权限。
所有物理模拟都在端侧通过 Canvas 和公式完成。
这正好符合隐私保护主题:学习类 App 可以把核心体验做丰富,而不一定要依赖拍照、上传和云端识别。
十、总结
物理模型详情页的模板化设计,是「物理视界」能承载 28 个模型的重要原因。
统一顶部栏、统一收藏逻辑、统一 Canvas 实验区、统一参数面板和数据面板,让用户在不同模型间切换时不会重新学习操作。
这篇文章对应的主题是:全新视觉与交互体验 + 隐私友好的端侧学习。
它体现了 OpenHarmony/HarmonyOS ArkUI 的一个优势:用统一组件结构和状态管理,把复杂知识点变成可交互的学习页面。✨

更多推荐



所有评论(0)