更新记录

1.1.2(2026-05-27)

补充文档

1.1.0(2026-05-27)

新增能力(Android、ios):

  • 点击聚焦 + AF 区域回切连续对焦
  • 双指缩放焦距,自动映射 setZoomPercent(0~100) 到设备 maxZoom
  • 新 props:default-cameratap-focuspinch-zoomflash-mode
  • 闪光灯 4 模式:off / torch / on / auto
  • 拍照 4 档画质预设:low / medium / high / ultra
  • 视频录制 4 档画质:QUALITY_LOW / 480P / 720P / 1080P
  • 视频录制最大时长限制(maxDurationMs),到时自动停止
  • 视频录制可选关闭音频(withAudio: false
  • 视频输出格式:mp4 / 3gp
  • 音频处理(AEC / NS / AGC),best-effort 模式,自动检测设备能力并在结果中返回
  • 新 actions:focusOnPointsetZoomPercentgetZoomInfo、`setFlas

平台兼容性

uni-app(4.72)

Vue2 Vue3 Chrome Safari app-vue app-nvue app-nvue插件版本 Android Android插件版本 iOS iOS插件版本 鸿蒙
- - - - × 1.1.2 5.0 1.1.2 13 1.1.2 ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
- - - - - - - - - - - -

uni-app x(4.72)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

hl-custom-photo

hl-custom-photo 当前提供两类能力:

  • 原生相机预览组件:预览、拍照、录像、切换摄像头、闪光灯、曝光、缩放、对焦、取帧、取色
  • 模块 API:compressImage 图片压缩

当前状态

平台 状态 说明
Android 已接入 当前主用平台,组件和压缩 API 都可用
iOS 已接入 组件和压缩 API 都可用,但事件桥接和部分能力表现与 Android 有差异

快速接入

1. 挂载组件

<template>
  <hl-custom-photo
    v-if="cameraMounted"
    class="camera-view"
    :autoStart="autoStartFlag"
    :scale="scale"
    :tapFocus="tapFocusFlag"
    :pinchZoom="pinchZoomFlag"
    :command="commandStr"
    @result="onCameraResult"
    @log="onCameraLog"
  />
</template>

2. 通过 command 下发动作

import { ref } from 'vue'

const commandStr = ref('')
const cameraMounted = ref(true)
const autoStartFlag = ref('1')
const tapFocusFlag = ref('1')
const pinchZoomFlag = ref('1')
const scale = ref('4:3')

let seq = 0
const pendingCallbacks = {}

function sendCommand(action, options, callback) {
  seq += 1
  if (callback) {
    pendingCallbacks[seq] = callback
  }
  commandStr.value = JSON.stringify({
    action,
    options: options || {},
    seq
  })
}

function normalizeEventPayload(event) {
  const detail = event?.detail ?? event

  if (detail?.dynamicJSONFields) {
    return detail.dynamicJSONFields
  }

  const payloadJson = detail?.payloadJson ?? detail?.__json
  if (typeof payloadJson === 'string' && payloadJson.length > 0) {
    try {
      return JSON.parse(payloadJson)
    } catch (e) {
      console.warn('[hl-custom-photo] payloadJson parse failed:', e)
    }
  }

  return detail
}

function onCameraResult(event) {
  const payload = normalizeEventPayload(event)
  const currentSeq = payload?.seq
  if (currentSeq != null && pendingCallbacks[currentSeq]) {
    const cb = pendingCallbacks[currentSeq]
    delete pendingCallbacks[currentSeq]
    cb(payload)
  }
}

function onCameraLog(event) {
  const payload = normalizeEventPayload(event)
  console.log('[native]', payload?.level, payload?.tag, payload?.msg)
}

sendCommand('takePhoto', {
  qualityPreset: 'high',
  returnFile: true
}, (result) => {
  console.log('photo result:', result)
})

3. 如果权限弹窗后预览没有恢复

nvue 页面里可直接卸载再挂载组件:

import { nextTick } from 'vue'

function restartCameraAfterPermission() {
  cameraMounted.value = false
  nextTick(() => {
    cameraMounted.value = true
  })
}

事件

事件 说明
@result 动作回调。通常包含 codemsgmessage,command 模式下还会带 actionseq
@log 原生日志透传。常见字段:leveltagmsgts

常见返回码约定:

code 含义
200 成功
201 业务失败或当前状态不满足
400 参数错误
401 权限失败
500 原生异常
501 当前平台还没迁移该能力

command 动作一览

下面这些 action 当前已经在 Android 和 iOS 的 dispatchAction 里接好,可以直接通过 command 使用。

基础控制

action options 说明
start { scale? } 启动相机
stop {} 停止相机
destroy {} 销毁组件并释放资源
getCamerasInfo {} 获取摄像头列表
switchCamera {} 前后摄像头切换
switchCameraById { id } 切换到指定摄像头
setIsbackCamera { isBack } 强制切前置或后置
reSetPreviewSize {} 父布局尺寸变化后,重新同步预览尺寸

拍照

action options 说明
takePhoto { qualityPreset?, quality?, width?, returnFile?, crop?, cropPx?, savePath?, fileName? } 拍照

补充:

  • qualityPreset 支持:lowmediumhighultra
  • crop 是百分比裁剪,格式 [x, y, w, h]
  • cropPx 是像素裁剪,格式 [x, y, w, h]
  • returnFile: true 时通常返回文件路径,否则通常返回 base64

视频录制

action options 说明
startRecord { quality?, withAudio?, maxDurationMs?, format?, audioProcessing?, savePath?, fileName?, orientation?, profile? } 开始录像
stopRecord {} 停止录像
isRecording {} 查询当前是否在录像
getAudioCapabilities {} 查询 AEC / NS / AGC 支持情况
hasProfile { profile } 查询设备是否支持指定录制档位

audioProcessing 结构示例:

{
  aec: true,
  ns: true,
  agc: false
}

闪光灯 / 曝光 / 缩放 / 对焦

action options 说明
setFlash { open } 简化版闪光灯控制,true 等价于 torchfalse 等价于 off
setFlashMode { mode } 完整模式,支持 offtorchonauto
getExposureCompensationVal {} 获取曝光补偿区间
setExposureCompensation { value } 设置曝光补偿
setZoom { level } 直接设置底层 zoom 原始值
setZoomPercent { percent } 按百分比设置缩放,建议范围 0~100
getZoomInfo {} 获取当前缩放百分比和最大原始值
focusOnPoint { x, y } 按预览 view 像素坐标对焦
configureTapFocus { enabled } 开关点击聚焦
configurePinchZoom { enabled } 开关双指缩放

iOS 额外兼容:

  • setZoomPercent({ percent, silent: true })
  • getZoomInfo({ silent: true })

silent: true 会执行原生动作,但不回发 @result

取帧 / 取色

action options 说明
startFrameListen {} 开始帧监听
stopFrameListen {} 停止帧监听
getFrameData { quality?, width?, crop?, cropPx? } 获取一帧图像 base64
getColor { point: [xPercent, yPercent] } 在预览帧的百分比坐标取单像素 RGB

注意事项:

  • getFrameData 前必须先调 startFrameListen
  • getColor.point 建议传 0~100 的百分比坐标
  • getColor 取的是单像素,不是区域平均色
  • 返回格式通常是 color: "r,g,b",例如 145,144,163

直接 expose 方法

除了 command,组件还直接暴露了一批方法,例如:

  • openCamera
  • setCameraConfigAndStart
  • setCropOption
  • startRealtimeFrame
  • pauseRealtimeFrame
  • setLogSink

但建议把这些当作高级用法:

  • 对业务页面,优先使用 command
  • 不是所有 expose 方法都已经映射进 command
  • 如果你新增了原生能力,并希望页面统一通过 command 使用,需要同步修改对应平台的 dispatchAction

画质映射

拍照 qualityPreset

档位 输出宽度 JPEG quality
low 640 70
medium 1280 80
high 1920 90
ultra 0,表示尽量保留原尺寸 100

视频 quality

档位 Android 映射
low CamcorderProfile.QUALITY_LOW
medium CamcorderProfile.QUALITY_480P
high CamcorderProfile.QUALITY_720P
ultra CamcorderProfile.QUALITY_1080P

设备不支持目标档位时,通常会返回 201

compressImage API

用法

import * as CustomPhoto from '@/uni_modules/hl-custom-photo'

CustomPhoto.compressImage(
  {
    path: '/storage/emulated/0/DCIM/Camera/test.jpg',
    maxWidth: 1080,
    maxHeight: 1920,
    quality: 80,
    format: 'webp',
    targetPath: '/storage/emulated/0/Android/data/xxx/cache/out.webp'
  },
  (result) => {
    if (result.code === 200) {
      console.log(result.path, result.width, result.height, result.size)
    }
  }
)

参数

字段 类型 说明
path string 输入图片路径
maxWidth number 最大输出宽度,可选
maxHeight number 最大输出高度,可选
quality number 输出质量,可选
format string jpeg / png / webp,可选
targetPath string 自定义输出路径,可选

返回结果

字段 说明
code 200 成功,其他值表示失败
msg 结果消息
path 输出文件路径
format 实际输出格式
width / height 输出宽高
size 输出文件大小
originalWidth / originalHeight / originalSize 原图信息
scale 相对原图的缩放比例

平台差异

1. @result / @log 事件对象

  • Android 端一般可以直接读取 event.detail
  • Android 若经过 UTS 包装,通常也能从 event.detail.dynamicJSONFields 拿到 plain object
  • iOS 端当前更稳妥的做法是优先读 payloadJson,其次兼容旧的 __json
  • 如果 iOS 页面看到的是空对象,不要先怀疑原生没执行,先排查事件解包逻辑

2. takePhoto

  • Android 更接近原生静态拍照输出
  • iOS 当前稳定实现更偏“预览帧截图后再加工”
  • 这意味着 iOS 最终分辨率上限受当前预览帧影响,不完全等同于传感器原图能力

3. 缩放

  • Android 适合直接走 getZoomInfo -> setZoomPercent
  • iOS 按钮式缩放更建议页面自己维护缩放状态,再调用 setZoomPercent
  • iOS 的 silent: true 适合“只下发控制,不关心本次回调”的场景

4. getColor

  • Android 当前更接近“开关式”取色
  • iOS 当前更接近“单次调用,单次返回”
  • 如果业务想两端交互一致,建议页面层统一封装成“点一次,回一次”

隐私、权限声明

1. 本插件需要申请的系统权限列表:

CAMERA / RECORD_AUDIO / FLASHLIGHT / READ_MEDIA_IMAGES

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

相机预览、拍照、录像与图片压缩能力会访问摄像头、麦克风与本地文件

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

暂无用户评论。