使用uni-app开发原生APP之自定义拍照功能

695 阅读2分钟

项目:北极象沉浸式翻译APP

一、uniapp - App居然没有支持内置拍照功能

对于App的拍照功能,一般来说最好是在App内唤起相机,尽量避免用户脱离App使用功能,类似身份验证那种。uniapp有camera组件,但是很可惜,这个组件目前只支持小程序类的应用使用,App暂时不支持

二、使用直播流来实现拍照?

找了一下文档,发现有个liver-pusher直播流,这个是用来做直播功能的,可以实现在应用内实时拍摄画面并传到后端,用快照功能能截图当前画面。

这不就是我要的吗,可以实时拍摄,还能拍摄快照,就是一个相机功能所需要的功能,看下可行性

三、live-pusher

从文档介绍来看,uniapp的<live-pusher>在app上已经完美支持了nvue,但是vue需要app平台在 3.4.1+

我的项目使用的是vue,考虑大家的版本可能不一致,所以以 plus.video.createLivePusher 做文章的讲解,如果平台版本合适的,直接参照文档<live-pusher>即可

1. 封装自定义相机组件

为了方便使用,我们封装一个类似<live-pusher>的组件:<custom-camera>

1) props

针对我们的需求,我们虽然用推流,但是我们实际上只需要快照功能就足够了,所以很多参数我们都不需要传递,只传递显示的参数即可

<script>
    export default {
        name: 'CustomCamera',
        props: {
            top: {
                type: String,
                default: '0px'
            },
            left: {
                type: String,
                default: '0px'
            },
            width: {
                type: String,
                default: '100%'
            },
            height: {
                type: String,
                default: '100%'
            },
            position: {
                type: String,
                default: 'static'
            }
        }
    }
</script>

topleft 控制推流画面的位置,默认是屏幕左上角开始

widthheight 控制推流画面的大小,默认占满整个屏幕

2) methods

简单封装已有的方法,都是现有的方法,眼见功夫

{
    methods: {
        getCurrentWebview() {
            return this.$mp.page.$getAppWebview()
        },
        stop() {
            this.pusher?.stop()
        },
        close() {
            this.pusher?.close()
        },
        switchCamera() {
            this.pusher?.switchCamera()
        },
        preview(switch = true) {
            this.pusher?.preview()
            if (switch) {
                this.switchCamera()
            }
        },
        snapshot() {
            this.pusher?.snapshot((res) => {
                this.stop()
                const { tempImagePath } = res

                if (tempImagePath) {
                    uni.compressImage({
                        src: tempImagePath,

                        // live-pusher 安卓快照会旋转90度
                        ...(this.isIos ? {} : { rotate: 270 }),
                        success: (res) => {
                            this.$emit('snapshot', res.tempFilePath)
                        }
                    })
                }
            })
        },
        init(tryRequestCamera = false) {
            const currentWebview = this.getCurrentWebview()
            this.pusher = plus.video.createLivePusher("photo-translate-camera", {  
                url:'',
                mode: 'FHD',
                muted: true,
                top: this.top,
                left: this.left,  
                width: this.width,  
                height: this.height,  
                position: 'static'
            });
            currentWebview.append(this.pusher);

            if (this.isIos) {
                this.preview()
            }
            
            if (tryRequestCamera) {
                this.close()
                return
            }

            this.$emit('rendered')
        }
    }
}

3) 外部使用
<template>
    <CustomCamera ref="cameraRef"
        @rendered="handleCameraRendered"
        @snapshot="handleSnapshot"
    />
</template>

<script>
export default {
    methods: {
        handleCameraRendered() {
            // 初始化相机辅助线
            // 初始化操作按钮
            // 初始化拍照提示
            // ...
        },
        handleSnapshot(url) {
            // 处理快照图片
            // ...
        }
    }
}
</script>
4) 注意事项

LivePusher实例是添加到webview的最顶层的,所以如果想要把操作按钮和辅助线之类的模块添加到相机上面,需要用到vocer-view

5) 页面展示

d6ee5535-3aaa-4b71-b764-7d47729fd8e0.jpg