uni.chooseImage 能满足“拍照+裁剪”基础需求,且推荐优先使用;它默认调起后置相机,支持 sourceType: ['camera'] 和 sizeType: ['compressed'],返回 tempFilePaths[0] 可直传裁剪组件,H5 也兼容,但 iOS 微信小程序需转 base64 或 blob 防跨域。

直接用 uni.chooseImage 拍照 + 第三方裁剪组件(如 vue-cropper 或 uni-app-cropper)是最稳、最省事的路径;想自定义取景框或强制前置摄像头,才必须上 <camera> 组件——但代价是平台限制多、权限逻辑重、裁剪得自己拼。
uni.chooseImage 能不能满足“拍照+裁剪”基础需求
能,而且推荐优先用它。它不暴露前后置控制,但真机上默认调起后置相机,90% 的证件照、商品图、扫码上传场景够用。
-
sourceType: ['camera']强制只走相机,避免用户误选相册 -
sizeType: ['compressed']可减小临时文件体积,加快后续裁剪和上传 - 返回的
tempFilePaths[0]是本地临时路径,可直接传给裁剪组件(如vue-cropper的src属性) - H5 端也能跑通,不用条件编译切逻辑
- 注意:iOS 微信小程序里,
uni.chooseImage返回的路径不能直接用于canvas绘图(会跨域),得先用uni.getFileSystemManager().readFile转成 base64 或临时 blob
为什么别一上来就写 <camera> 组件
因为 <camera> 在微信小程序里有硬性 DOM 限制:必须是 <template> 的**直接子节点**,包一层 <view> 或套个 v-if 就白屏;App 端虽无此限制,但闪光灯、缩放等属性在部分安卓机型上静默失效,UI 显示和实际行为可能不一致。
- 要稳定切前置,只能靠
device-position="front",但 iOS 和多数安卓无法在uni.chooseImage中实现,这是它唯一不可替代的点 - 拍照必须用
uni.createCameraContext().takePhoto(),不能和录像 API 混用,否则在小程序里会静默失败 - 取景框蒙层要用
cover-view/cover-image,普通view会被相机层盖住 - 获取到的图片路径是本地 file:// 协议,上传前需用
uni.uploadFile直传,不能走 base64(iOS 会卡死)
裁剪环节最容易翻车的三个地方
裁剪不是“找个插件绑上就行”,关键在输入源、坐标系和输出格式三者对齐。
- 输入图若来自
<camera>,需注意设备方向:Android 多数返回竖拍图但 EXIF orientation=90,直接裁会歪;要用uni.getImageInfo读 orientation 并旋转 canvas - 裁剪组件的宽高比设置必须和预览容器一致,否则拖拽区域错位——比如你设了
aspect=1(正方形),但预览<image>用了mode="widthFix",视觉上就对不上 - 裁剪后输出建议用
quality: 0.8+format: 'jpg',避免 PNG 体积暴增;微信小程序里canvas.toTempFilePath不支持 webp,别硬配
权限和真机调试绕不开的坑
所有相机相关操作,在 Android 和 iOS 上都依赖系统级授权,模拟器和 H5 完全不可测,必须真机连 IDE 调试。
- App 端首次调用前,必须先
uni.authorize({scope: 'scope.camera'}),拒绝后得跳系统设置页,用plus.runtime.openURL('native://settings') - 微信小程序里,
scope.camera授权弹窗只在uni.chooseImage或<camera>首次渲染时触发,提前调authorize无效 - Android 12+ 要求在
manifest.json里显式声明"permissions": ["android.permission.CAMERA"],否则打包后直接黑屏 - iOS 打包需在
manifest.json → "mp-weixin" → "requiredPrivateInfos"加"camera",否则提审被拒
真正难的不是调起相机,而是让不同端的临时路径、方向信息、裁剪坐标、上传协议全部对齐——这些细节没压平,上线后用户拍出来的图永远差那么 10 度或 20 像素。


















