在HarmonyOS NEXT 6.1.1(API 24)中,Camera Kit为专业影像场景带来了一项关键能力——无级手动对焦。对于微距拍摄、影视级拉焦或扫码场景下的焦段锁定,这套API让开发者能够通过[0.0, 1.0]范围的浮点数直接驱动对焦马达,彻底告别自动对焦的"拉风箱"问题。本文基于实际Demo,梳理ArkTS与C API两条实现路径,并整理避坑要点。
一、手动对焦API概览
在HarmonyOS 6.1.1中,手动对焦能力被封装在PhotoSession对象中,提供了两个核心接口族:
1. 能力查询:isFocusDistanceSupported(),返回boolean值。对于部分不支持音圈马达(VCM)的前置定焦镜头,通常会返回false,因此在实际调用对焦控制前,需要先通过该接口做能力探测。
2. 无级对焦控制:getFocusDistance()和setFocusDistance()。取值范围标准化为[0.0, 1.0],其中0.0对应镜头物理极限的最近对焦距离(即超级微距模式下的焦点位置),1.0代表无限远(Infinity),同时也是相机默认的对焦状态。任意中间值都会等比例映射到真实物理对焦行程。
二、ArkTS侧实现路径
在ArkTS层,手动对焦的调用非常直观。以下是一个"对焦控制舱"Demo的关键流程:查询支持性、通过Slider实时调节对焦参数、记录操作日志。
项目结构方面,主要在entry模块新增一个页面CameraFocusDemo.ets,并在main_pages.json中注册路由。
核心代码片段如下:
- import { camera } from '@kit.CameraKit';
- import { BusinessError } from '@kit.BasicServicesKit';
- // 1. 检查是否支持手动对焦
- checkSupport(): void {
- try {
- // photoSession.isFocusDistanceSupported()
- let supported = true;
- this.isSupported = supported;
- } catch (e) {
- this.appendLog(`检测异常: ${(e as BusinessError).code}`);
- }
- }
- // 2. 响应Slider拉动,下发对焦指令
- onFocusChange(value: number): void {
- this.currentFocus = value;
- try {
- // photoSession.setFocusDistance(value)
- if (value === 0.0) {
- this.appendLog('已到达极限微距 (0.0)');
- } else if (value === 1.0) {
- this.appendLog('已到达无限远 (1.0)');
- }
- } catch (e) {
- this.appendLog(`对焦失败: ${(e as BusinessError).code}`);
- }
- }
复制代码
Slider组件需要注意:拖拽事件的回调频率极高(可能达到60fps甚至120fps),如果在Moving过程中频繁调用setFocusDistance,会由于底层IPC与硬件驱动的开销造成卡顿,甚至触发错误码7400102或底层死锁。因此务必只在拖拽结束(SliderChangeMode.End)或点击(SliderChangeMode.Click)时下发指令。
- Slider({
- value: this.currentFocus,
- min: 0.0,
- max: 1.0,
- step: 0.01,
- style: SliderStyle.OutSet
- })
- .width('100%')
- .onChange((value: number, mode: SliderChangeMode) => {
- // 仅在拖拽结束或点击时触发,避免频繁发指令
- if (mode === SliderChangeMode.End || mode === SliderChangeMode.Click) {
- this.onFocusChange(value);
- }
- })
- .enabled(this.isSupported)
复制代码
三、C API侧的对焦马达直驱
对于在C++ NDK层做计算视觉或游戏开发的场景,Camera Kit同样提供了原生接口,避免跨语言调用的开销。相关API位于capture_session.h中:
- OH_CaptureSession_IsFocusDistanceSupported:能力探针,输出bool
- OH_CaptureSession_GetFocusDistance:输出float指针(0.0f ~ 1.0f)
- OH_CaptureSession_SetFocusDistance:输入float驱动硬件
返回状态码均为Camera_ErrorCode类型(如CAMERA_OK)。这套C接口的价值在于,OpenGL/Vulkan的AR渲染管线可以直接在底层干预空间深度,无需频繁穿越JSI/Native边界。
四、避坑指南
1. 防抖与马达打架:同时开启激进的光学防抖(OIS)偏移注入和手动对焦时,底层镜头马达可能处于高频震动状态。在工业视觉或扫码场景中使用强制微距对焦时,建议锁定OIS或降低干预频率。
2. 频控警告:拖拽回调不等于对焦指令下发时机。setFocusDistance底层通过IPC与硬件驱动通信,高频调用会产生显著开销。最佳实践是仅在交互结束时下发一次,或者自行做节流/去抖。
3. Session状态约束:对焦距离强依赖底层硬件状态机。只能在CaptureSession正常初始化并完成Config之后调用相关接口,否则会抛出7400103(Session not config)错误。
五、总结
HarmonyOS 6.1.1通过setFocusDistance及对应的Native C API,补全了Camera Kit在焦段控制上的关键拼图。无论是扫码器、显微工具软件还是专业影像APP,都能通过这套标准化接口在毫厘之间掌控对焦行程。建议开发者在实际接入时,先做支持性探测,再合理设计UI交互的频率控制,避免性能问题。
(本文基于HarmonyOS NEXT 6.1.1 API 24实测经验整理,代码基于真实项目精简。) |