更新记录

1.0.0(2026-06-08)

发布初始版本1.0.0


平台兼容性

uni-app(4.07)

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

uni-app x(4.07)

Chrome Safari Android Android插件版本 iOS 鸿蒙 微信小程序
- - 5.0 1.0.0 - - -

其他

多语言 暗黑模式 宽屏模式
×

该插件使用简单,编写,易于集成。

一、使用举例:

<template>
    <view class="content">
        <view>
            <text class="title">{{title}}</text>
        </view>
        <!-- 使用你的相机组件,标签名与uts文件中定义的name一致 -->
        <view class="camera-wrap">
            <st-smart-camera ref="camera" class="camera-view" size="300rpx" displayShape="circle" @ready="onCameraReady"
                @captureResult="handleCaptureResult" @startResult="handleStartResult" @changeResult="handleChangeResult"
                @stopResult="handleStopResult" />
        </view>

        <!-- 操作按钮 -->
        <view class="controls">
            <button @click="startCamera()">开启相机</button>
            <button @click="switchCamera()">切换内置前后摄像头</button>
            <button @click="takePicture()">拍照</button>
            <button @click="stopCamera()">关闭相机</button>
        </view>

        <!-- 简单的照片预览 -->
        <image v-if="photoPath" :src="photoPath" style="width: 300rpx; height: 300rpx;"></image>
    </view>
</template>

<script>
    export default {
        data() {
            return {
                title: 'Hello',
                photoPath: '',
                displayShape: 'circle',
                startTimer: null,
                isCameraStarting: false,
                isCameraStarted: false
            }
        },
        // --- 生命周期钩子应该与 methods 平级 ---
        onReady() {},
        methods: {
            onCameraReady() {
                uni.showToast({
                    title: '相机就绪,请点击开启',
                    icon: 'none'
                });
            },
            stopCamera() {
                const camera = this.$refs.camera;
                if (camera) {
                    if (this.startTimer) {
                        clearTimeout(this.startTimer)
                        this.startTimer = null
                    }
                    this.isCameraStarting = false
                    uni.showLoading({
                        title: '关闭中...'
                    });
                    // @ts-ignore
                    camera.stopCamera();
                }
            },
            handleCaptureResult(result) {
                this.title = 'onHide'
                let detail = result.detail
                if (detail.errMsg === 'takePicture:ok') {
                    this.photoPath = detail.tempUriString;
                    uni.showModal({
                        title: '拍照成功',
                        showCancel: false
                    });
                } else {
                    uni.showToast({
                        title: detail.errMsg,
                        icon: 'none'
                    });
                }
            },
            handleStartResult(result) {
                if (this.startTimer) {
                    clearTimeout(this.startTimer)
                    this.startTimer = null
                }
                uni.hideLoading()
                let detail = result.detail
                if (detail.errMsg.indexOf('startCamera:ok') !== 0) {
                    this.isCameraStarting = false
                    this.isCameraStarted = detail.errMsg.indexOf('摄像头已在运行') !== -1
                    uni.showToast({
                        title: detail.errMsg,
                        icon: 'none'
                    });
                } else {
                    this.isCameraStarting = false
                    this.isCameraStarted = true
                    uni.showToast({
                        title: '相机已开启',
                        icon: 'none'
                    });
                }
            },
            handleStopResult(result) {
                uni.hideLoading()
                let detail = result.detail
                if (detail.errMsg !== 'stopCamera:ok') {
                    if (detail.errMsg.indexOf('摄像头未启动') !== -1) {
                        this.isCameraStarted = false
                    }
                    uni.showToast({
                        title: detail.errMsg,
                        icon: 'none'
                    });
                } else {
                    this.isCameraStarting = false
                    this.isCameraStarted = false
                    uni.showToast({
                        title: '相机已关闭',
                        icon: 'none'
                    });
                }
            },
            handleChangeResult(result) {
                let detail = result.detail
                if (detail.errMsg !== 'switchCamera:ok') {
                    uni.showToast({
                        title: detail.errMsg,
                        icon: 'none'
                    });
                }
            },
            async startCamera() {
                if (this.isCameraStarting) {
                    uni.showToast({
                        title: '相机正在开启',
                        icon: 'none'
                    });
                    return;
                }
                if (this.isCameraStarted) {
                    uni.showToast({
                        title: '相机已开启',
                        icon: 'none'
                    });
                    return;
                }
                // #ifdef APP-PLUS
                const status = await new Promise((resolve) => {
                    plus.android.requestPermissions(['android.permission.CAMERA'], (result) => {
                        resolve(result.granted.length > 0);
                    });
                });
                if (!status) {
                    uni.showToast({
                        title: '相机权限被拒绝',
                        icon: 'none'
                    });
                    return;
                }
                // #endif

                const camera = this.$refs.camera;
                console.log("========camera ref=======", camera)
                if (camera) {
                    uni.showLoading({
                        title: '开启中...'
                    });
                    if (this.startTimer) {
                        clearTimeout(this.startTimer)
                    }
                    this.startTimer = setTimeout(() => {
                        this.startTimer = null
                        this.isCameraStarting = false
                        uni.hideLoading()
                        uni.showToast({
                            title: '开启相机超时',
                            icon: 'none'
                        });
                    }, 8000)
                    this.isCameraStarting = true
                    // @ts-ignore
                    camera.startCamera();
                }
            },
            switchCamera() {
                const camera = this.$refs.camera;
                if (camera) {
                    // @ts-ignore
                    camera.switchCamera();
                }
            },
            takePicture() {
                const camera = this.$refs.camera;
                if (camera) {
                    console.log("JS: 发送拍照指令...");
                    // @ts-ignore
                    camera.capturePhoto();
                }
            },
        }
    }
</script>

<style>
    .content {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }

    .logo {
        height: 200rpx;
        width: 200rpx;
        margin-top: 200rpx;
        /* #ifndef APP-PLUS-NVUE */
        margin-left: auto;
        margin-right: auto;
        /* #endif */
        margin-bottom: 50rpx;
    }

    .title {
        font-size: 36rpx;
        color: #8f8f94;
    }

    .camera-wrap {
        width: 300rpx;
        height: 300rpx;
        overflow: hidden;
        border-radius: 150rpx;
    }

    .camera-view {
        width: 300rpx;
        height: 300rpx;
    }
</style>

注意:

1、需要自定义基座运行。

2、根据官方文档,需要在nvue/uvue页面进行使用。

3、在有内置和外置摄像头同时存在的情况下,会优先使用外置。如果没有外置摄像头则会使用内置,如手机。外置摄像头适用于特殊设备。

4、在使用内置摄像头时,默认使用的前置摄像头。

二、方法和属性介绍:

@ready:相机准备好的回调

@captureResult:拍照结果回调

@startResult:相机启动结果回调

@changeResult:前后置切换相机回调

@stopResult:关闭相机回调

displayShape:显示形状圆形(circle)和方形(square),默认圆形

size:显示大小(比如300rpx)

隐私、权限声明

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

<uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.RECORD_AUDIO" /> <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" android:required="false" />

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

插件不采集任何数据

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

暂无用户评论。