更新记录
1.0.0(2026-09-26)
原生内嵌相机
平台兼容性
uni-app(5.26)
| Vue2 | Vue3 | Chrome | Safari | app-vue | app-vue插件版本 | app-nvue | app-nvue插件版本 | Android | Android插件版本 | iOS | iOS插件版本 | 鸿蒙 | 鸿蒙插件版本 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| √ | √ | × | × | √ | 1.0.0 | √ | 1.0.0 | 10.0 | 1.0.0 | 13 | 1.0.0 | 16 | 1.0.0 |
| 微信小程序 | 支付宝小程序 | 抖音小程序 | 百度小程序 | 快手小程序 | 京东小程序 | 鸿蒙元服务 | QQ小程序 | 飞书小程序 | 小红书小程序 | 快应用-华为 | 快应用-联盟 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| × | × | × | × | × | × | × | × | × | × | × | × |
yao-embed-camera
原生内嵌相机 UTS 组件(uni-app 兼容模式组件),在页面中内嵌一个相机预览区域,支持拍照、手电筒、前后摄像头切换。
开发文档
必须使用 nvue 页面
本组件是原生内嵌组件,App 端必须在 .nvue 页面中使用(.vue 页面无法渲染原生预览)。
使用示例(Vue2 · nvue 页面)
<template>
<view class="page">
<view class="camera-box" :style="{ width: camW + 'px', height: camH + 'px' }">
<yao-embed-camera ref="cameraRef"
:style="{ width: camW + 'px', height: camH + 'px' }"
@photo-taken="onPhotoTaken"
@picture-size="onPictureSize"
@camera-error="onCameraError"
@camera-switched="onCameraSwitched" />
</view>
<view class="btn-row">
<view class="btn" @click="onShoot"><text class="btn-txt">拍照</text></view>
<view class="btn" @click="onSwitch"><text class="btn-txt">切换</text></view>
<view class="btn" @click="onFlash"><text class="btn-txt">闪光灯</text></view>
</view>
<image v-if="photoPath" class="photo" :src="photoPath" mode="aspectFit"></image>
</view>
</template>
<script>
export default {
data() {
return {
camW: 375,
camH: 500,// 默认 3:4
photoPath: ''
}
},
onLoad() {
const sys = uni.getSystemInfoSync();
this.camW = sys.windowWidth;
this.camH = Math.round(this.camW * 4 / 3);
},
methods: {
getParam(e, key) {
const d = (e && e.detail) ? e.detail : {};
if (d[key] != null) return d[key];
if (d.dynamicJSONFields && d.dynamicJSONFields[key] != null) {
return d.dynamicJSONFields[key];
}
return null;
},
onPictureSize(e) {
const w = this.getParam(e, 'width');
const h = this.getParam(e, 'height');
if (w && h) {
// 按实际照片比例适配预览框,保证所见即所得
this.camH = Math.round(this.camW * h / w);
}
},
onPhotoTaken(e) {
const path = this.getParam(e, 'path');
if (path) this.photoPath = path; // 照片在应用缓存目录,可直接显示
},
onCameraError(e) {
uni.showToast({ title: this.getParam(e, 'message') || '相机错误', icon: 'none' });
},
onCameraSwitched(e) {
const facing = this.getParam(e, 'facing');
uni.showToast({ title: facing === 'front' ? '已切到前置' : '已切到后置', icon: 'none' });
},
onShoot() {
this.$refs.cameraRef.takePhoto();
},
onSwitch() {
this.$refs.cameraRef.switchCamera();
},
onFlash() {
this.$refs.cameraRef.toggleFlashlight();
}
}
}
</script>
<style>
.page { flex: 1; background-color: #000000; align-items: center; }
.camera-box { background-color: #222222; }
.btn-row { flex-direction: row; margin-top: 20rpx; }
.btn { padding: 16rpx 40rpx; margin: 0 16rpx; background-color: #007aff; border-radius: 8rpx; }
.btn-txt { color: #ffffff; font-size: 28rpx; }
.photo { width: 375px; height: 500px; margin-top: 20rpx; }
</style>
使用示例(Vue3 · nvue 页面)
<template>
<view class="page">
<view class="camera-box" :style="{ width: camW + 'px', height: camH + 'px' }">
<yao-embed-camera ref="cameraRef"
:style="{ width: camW + 'px', height: camH + 'px' }"
@photo-taken="onPhotoTaken"
@picture-size="onPictureSize"
@camera-error="onCameraError"
@camera-switched="onCameraSwitched" />
</view>
<view class="btn-row">
<view class="btn" @click="onShoot"><text class="btn-txt">拍照</text></view>
<view class="btn" @click="onSwitch"><text class="btn-txt">切换</text></view>
</view>
<image v-if="photoPath" class="photo" :src="photoPath" mode="aspectFit"></image>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
const cameraRef = ref(null)
const camW = ref(375)
const camH = ref(500)
const photoPath = ref('')
onLoad(() => {
const sys = uni.getSystemInfoSync();
camW.value = sys.windowWidth;
camH.value = Math.round(camW.value * 4 / 3);
})
const getParam = (e, key) => {
const d = (e && e.detail) ? e.detail : {};
if (d[key] != null) return d[key];
if (d.dynamicJSONFields && d.dynamicJSONFields[key] != null) {
return d.dynamicJSONFields[key];
}
return null;
}
const onPictureSize = (e) => {
const w = getParam(e, 'width');
const h = getParam(e, 'height');
if (w && h) {
camH.value = Math.round(camW.value * h / w);
}
}
const onPhotoTaken = (e) => {
const path = getParam(e, 'path');
if (path) photoPath.value = path;
}
const onCameraError = (e) => {
uni.showToast({ title: getParam(e, 'message') || '相机错误', icon: 'none' });
}
const onCameraSwitched = (e) => {
const facing = getParam(e, 'facing');
uni.showToast({ title: facing === 'front' ? '已切到前置' : '已切到后置', icon: 'none' });
}
const onShoot = () => cameraRef.value.takePhoto()
const onSwitch = () => cameraRef.value.switchCamera()
</script>
<style>
.page { flex: 1; background-color: #000000; align-items: center; }
.camera-box { background-color: #222222; }
.btn-row { flex-direction: row; margin-top: 20rpx; }
.btn { padding: 16rpx 40rpx; margin: 0 16rpx; background-color: #007aff; border-radius: 8rpx; }
.btn-txt { color: #ffffff; font-size: 28rpx; }
.photo { width: 375px; height: 500px; margin-top: 20rpx; }
</style>
API
方法(通过 ref 调用)
| 方法 | 说明 |
|---|---|
| takePhoto() | 拍照,完成后触发 photo-taken 事件 |
| toggleFlashlight() | 切换手电筒开关(仅后置摄像头有效;切换摄像头后状态自动重置为关闭) |
| switchCamera() | 切换前/后摄像头,成功后触发 camera-switched 事件 |
事件
| 事件 | 回调参数 | 说明 |
|---|---|---|
| photo-taken | { path: string } |
拍照完成,path 为照片本地路径(应用缓存目录,可直接作为 image src) |
| picture-size | { width: number, height: number } |
照片尺寸(竖屏宽高,建议据此适配预览框比例) |
| camera-error | { message: string } |
权限被拒绝 / 相机打开失败等错误信息 |
| camera-switched | { facing: string } |
摄像头已切换,"front" 前置 / "back" 后置 |
平台配置
HarmonyOS
组件初始化前会自动弹出相机授权框,但需先在项目根目录 harmony-configs/entry/src/main/module.json5 中声明权限(若无 harmony-configs 目录请先运行一次鸿蒙构建让其生成,或手动创建):
{
"module": {
"requestPermissions": [
{ "name": "ohos.permission.INTERNET" },
{
"name": "ohos.permission.CAMERA",
"reason": "$string:camera_permission_reason",
"usedScene": {
"abilities": ["EntryAbility"],
"when": "inuse"
}
}
]
}
}
并在 harmony-configs/entry/src/main/resources/base/element/string.json(zh_CN / en_US 同理)中补充文案:
{
"string": [
// ...原有条目保持不变...
{
"name": "camera_permission_reason",
"value": "需要使用相机进行拍照"
}
]
}

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 271
赞赏 6
下载 12641178
赞赏 1950
赞赏
京公网安备:11010802035340号