【OpenHarmony/HarmonyOs 】凸透镜成像实验:光路绘制、成像公式与禁止 AI 识图的学习方案
【OpenHarmony/HarmonyOs 】凸透镜成像实验:光路绘制、成像公式与禁止 AI 识图的学习方案
本文基于我的 OpenHarmony/HarmonyOS 项目「物理视界 PhysicsVision」整理。项目中的「凸透镜成像」模型通过 Canvas 绘制主光轴、透镜、焦点、物体、像和两条典型光线,并根据物距和焦距实时计算成像类型。
这一篇对应“沉浸光感”和“禁止 AI 识图、隐私保护方案”的主题:不用拍照识题,也能把光学知识讲清楚。🔍
一、为什么凸透镜成像不一定需要拍照识题?
很多教育 App 会把光学题做成“拍照识别题目,然后给答案”。
但这种方式有几个问题:
- 需要相机权限;
- 图片可能包含学生个人信息;
- 学生容易直接看答案;
- 对理解成像规律帮助有限。
「物理视界」选择了另一种方式:
不拍照、不上传、不识图,而是让学生自己调节焦距、物距和物体高度,看成像结果如何变化。
这更适合物理学习,因为凸透镜成像的重点不是答案,而是规律。
二、核心参数
页面定义了三个输入参数:
@State focalLength: number = 60
@State objectDist: number = 150
@State objectHeight: number = 50
还有三个计算结果:
@State imageDist: number = 0
@State imageHeight: number = 0
@State imageType: string = ''
这对应物理中的:
- 焦距
f; - 物距
u; - 像距
v; - 放大率;
- 成像性质。
三、成像公式计算
项目使用薄透镜公式:
calculate(): void {
let u = this.objectDist
let f = this.focalLength
if (Math.abs(u - f) < 1) {
this.imageDist = 9999
this.imageHeight = 9999
this.imageType = '平行光(不成像)'
return
}
let v = (u * f) / (u - f)
this.imageDist = v
this.imageHeight = -v / u * this.objectHeight
}
公式本质是:
1/f = 1/u + 1/v
整理后得到:
v = uf / (u - f)
这里完全在端侧计算,不需要调用 AI 服务。
四、成像类型判断
根据物距和焦距关系,判断成像类型:
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 = '正立放大虚像'
这正是初中光学常见知识点:
u > 2f:倒立缩小实像;u = 2f:倒立等大实像;f < u < 2f:倒立放大实像;u < f:正立放大虚像。
通过代码,物理规律被明确地表达出来。
五、绘制主光轴和透镜
Canvas 中先绘制主光轴:
ctx.strokeStyle = '#B2BEC3'
ctx.lineWidth = 1
ctx.beginPath()
ctx.moveTo(10, centerY)
ctx.lineTo(w - 10, centerY)
ctx.stroke()
再绘制透镜:
ctx.strokeStyle = '#1A73E8'
ctx.lineWidth = 3
ctx.beginPath()
ctx.moveTo(centerX, centerY - 80)
ctx.lineTo(centerX, centerY + 80)
ctx.stroke()
蓝色透镜线条在浅色和深色背景下都比较清晰。
六、绘制焦点和 2F 点
let fPx = this.focalLength * scale
ctx.fillStyle = '#FF6D00'
ctx.beginPath()
ctx.arc(centerX - fPx, centerY, 4, 0, Math.PI * 2)
ctx.fill()
ctx.beginPath()
ctx.arc(centerX + fPx, centerY, 4, 0, Math.PI * 2)
ctx.fill()
ctx.fillText('F', centerX - fPx, centerY + 16)
ctx.fillText("F'", centerX + fPx, centerY + 16)
焦点和 2F 点是判断成像规律的关键参照。
把它们画在图上,学生能更容易理解“物体在 2F 外、F 和 2F 之间、F 内”的区别。
七、绘制物体和像
物体用红色箭头表示:
let objX = centerX - this.objectDist * scale
let objTop = centerY - this.objectHeight * 0.8
ctx.strokeStyle = '#F44336'
ctx.lineWidth = 3
ctx.beginPath()
ctx.moveTo(objX, centerY)
ctx.lineTo(objX, objTop)
ctx.stroke()
像用绿色箭头表示:
let imgX = centerX + this.imageDist * scale
let imgH = this.imageHeight * 0.8
let imgTop = centerY - imgH
let isVirtual = this.imageDist < 0
if (isVirtual) {
ctx.setLineDash([5, 5])
}
ctx.strokeStyle = '#4CAF50'
ctx.beginPath()
ctx.moveTo(imgX, centerY)
ctx.lineTo(imgX, imgTop)
ctx.stroke()
ctx.setLineDash([])
虚像使用虚线,这是一个很适合教学的视觉约定。
八、绘制两条典型光线
项目绘制了平行光线和过光心光线:
ctx.strokeStyle = '#FFB74D'
ctx.lineWidth = 1
ctx.beginPath()
ctx.moveTo(objX, objTop)
ctx.lineTo(centerX, objTop)
ctx.lineTo(imgX, imgTop)
ctx.stroke()
ctx.beginPath()
ctx.moveTo(objX, objTop)
ctx.lineTo(imgX, imgTop)
ctx.stroke()
这比只显示像的位置更好,因为学生能看到成像是如何由光路决定的。
九、滑块调参:主动探索规律
焦距、物距和物体高度都用 Slider 控制:
Slider({ value: this.objectDist, min: 20, max: 250, step: 1 })
.trackColor($r('app.color.slider_track'))
.selectedColor('#1A73E8')
.onChange((v: number) => {
this.objectDist = v
this.calculate()
})
每次滑动都会重新计算并绘图。
这让学生可以自己观察:
- 物距变小时像距怎么变;
- 什么时候不成像;
- 实像和虚像如何切换;
- 像的大小如何变化。
十、总结
凸透镜成像页面很好地体现了“禁止 AI 识图”的另一种学习方案。
不拍照、不上传、不识别题目,而是让学生通过参数调节和光路观察理解规律。
这篇文章对应的主题是:沉浸光感 + 禁止 AI 识图 + 隐私友好学习。
对 OpenHarmony/HarmonyOS 开发者来说,它也展示了 Canvas 在光学教学中的实用价值。🔍

更多推荐



所有评论(0)