更新记录

1.0.0(2026-06-27)

初次发布


平台兼容性

uni-app(4.71)

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

uni-app x(4.71)

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

camera-full-preview

插件说明

app端打开全屏相机拍摄,横屏拍摄的照片、视频自动旋转竖向展示,自动适配相机质量。

在uni-app的nvue页面使用并在安卓设备中测试正常,其余场景及设备未测试,请使用者自行测试。

使用方法

uts兼容模式组件支持nvue页面,不支持vue页面。导入插件后在nvue页面中直接用插件名称作为组件名使用,无需引入。

下边示例代码中 getPermission 获取设备权限方法,是另一个插件,插件地址为 getPermission

<template>
    <view>
        <view v-if="takeMedia.fileType" :style="{ height: cameraHeight }">
            <image v-if="takeMedia.fileType == 'image'" :src="takeMedia.tempFilePath" mode="widthFix"
                class="media-preview">
            </image>
            <video v-if="takeMedia.fileType == 'video'" :src="takeMedia.tempFilePath"
                :poster="takeMedia.thumbTempFilePath" class="media-preview" :style="{ height: cameraHeight }"></video>
        </view>

        <camera-full-preview v-else ref="cameraView" @onSuccess="cameraSuccess" @onError="cameraError"
            :style="{ height: cameraHeight }"></camera-full-preview>
        <view class="btn-cnt">
            <button v-if="takeMedia.fileType" size="mini" @click="initTakeMedia">重拍</button>
            <template v-else>
                <button size="mini" @click="cameraSwitch">翻转</button>
                <button size="mini" @click="takePic">拍照</button>
                <button v-if="videoTime" size="mini" @click="videoEnd">停止录像</button>
                <button v-else size="mini" @click="videoStart">开始录像</button>
                <text v-if="videoTime">{{ videoTime + '/' + videoDuration }}秒</text>
            </template>

        </view>

    </view>
</template>

<script setup>
    import { ref } from 'vue'
    import { onUnload } from '@dcloudio/uni-app'
    import { getPermission } from '@/uni_modules/app-check-permission/js_sdk/permission.js'

    let cameraView = ref(null)
    let videoDuration = 10
    let videoTime = ref(0)
    let timerVideo = null
    let videoIsEnd = false
    let takeMedia = ref({})
    const cameraHeight = ref(uni.getSystemInfoSync().screenHeight - 150)

    let perms = ['android.permission.CAMERA', 'android.permission.RECORD_AUDIO'];
    if (plus.os.name === 'iOS') {
        perms = ['camera', 'record']
    }
    getPermission(perms, '相机和麦克风')

    const initTakeMedia=()=>{
        takeMedia.value = {}
    }

    const takePic = () => {
        initTakeMedia()
        cameraView.value.takePhoto()
    }

    const videoStart = () => {
        initTakeMedia()
        cameraView.value.startRecording()
    }
    const videoEnd = () => {
        if (videoIsEnd) return
        cameraView.value.stopRecording()
    }

    function videoTimeAdd() {
        clearVideoTimer()
        videoTime.value = 1

        timerVideo = setInterval(() => {
            if (videoTime.value < videoDuration) {
                videoTime.value++
            } else {
                videoEnd()
                clearVideoTimer()
            }
        }, 1000)
    }

    function clearVideoTimer() {
        if (timerVideo) {
            clearInterval(timerVideo)
            timerVideo = null
            videoTime.value = 0
        }
    }
    const cameraSwitch = () => {
        cameraView.value.switchCamera()
    }

    //事件返回
    const cameraSuccess = (res) => {
        const detail = res?.detail?.dynamicJSONFields
        switch (detail?.name) {
            case 'initialize':
                //初始化成功
                cameraView.value.getZoomState();
                break;
            case 'switchCamera':
                //切换摄像头
                setTimeout(() => {
                    cameraView.value.getZoomState();
                }, 500)
                break;
            case 'startVideo':
                //开始录制
                videoTimeAdd()
                videoIsEnd = false
                break;
            case 'endVideo':
                //结束录制,返回视频路径和封面路径,格式 "videoPath|||coverPath"
                const rawData = detail?.data || ''
                const parts = rawData.split('|||')
                takeMedia.value = {
                    tempFilePath: parts[0] || '',
                    thumbTempFilePath: parts[1] || '',
                    fileType: 'video'
                }
                videoIsEnd = true
                clearVideoTimer()
                break;
            case 'pahto':
                //拍照回调
                takeMedia.value = {
                    tempFilePath: detail?.data,
                    fileType: 'image'
                }
                break;
        }
    }

    //错误回调事件
    const cameraError = (res) => {
        const data = res.detail?.dynamicJSONFields || {}
        uni.showToast({
            title: data.error || '错误!',
            icon: 'none'
        })

        if (cameraType.value == 1) {
            videoIsEnd = true
            clearVideoTimer()
        }
    }

    onUnload(() => {
        clearVideoTimer()
    })
</script>

<style scoped>
    .media-preview {
        width: 750rpx;
    }

    .btn-cnt {
        flex-direction: row;
        justify-content: space-around;
        align-items: center;
        margin-top: 5px;
    }
</style>

隐私、权限声明

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

<uses-permission android:name="android.permission.CAMERA"/>, <uses-permission android:name="android.permission.RECORD_AUDIO"/>

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

插件不采集任何数据

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

暂无用户评论。