小程序-拍照截取指定区域图片

1,393 阅读1分钟

拍摄截取指定区域内图片,上传图片从后端接口获取相应的图片

html

<template>
    <view class="photo-view">
        <camera
            v-if="isShowCamera"
            class="camera-box"
            devic-position="width"
            flash="off"
            :style="{ width: windowWidth + 'px', height: windowHeight + 'px' }"
        >
            <cover-view class="camerabgImage">
                <cover-view class="active">
                    <cover-image class="active-image" src="@/static/images/camera-photo.png"></cover-image>
                    <cover-view class="text">请将VIN码放入框中,点击拍照进行识别</cover-view>
                    <cover-view class="btn" @tap="takePhotoAction">
                        <cover-view class="button"></cover-view>
                    </cover-view>
                    <cover-view class="btn" @tap="takeAlbumAction">
                        <cover-view>相册</cover-view>
                    </cover-view>
                </cover-view>
            </cover-view>
        </camera>

        <canvas
            v-if="isShowImage"
            canvas-id="image-canvas"
            :style="{ width: windowWidth + 'px', height: windowHeight + 'px' }"
        ></canvas>
    </view>
</template>

js



<script>

export default {
    data() {
        return {
            isShowCamera: false,
            isShowImage: true,
            image: '',
            windowWidth: '',
            windowHeight: '',
            options: {
                //type:1 //区分是哪个页面进入的:首页1、血糖历史记录页面2、添加血糖页面3、
            },
        }
    },
    onLoad(options) {
        console.log(options, typeof options.type, 'options')

        this.options = options
        this.ctx = uni.createCameraContext()
        let { windowWidth, windowHeight } = uni.getSystemInfoSync()
        this.windowWidth = windowWidth
        this.windowHeight = windowHeight
    },
    onShow: function () {
        var that = this
        uni.authorize({
            scope: 'scope.camera',
            success: function (res) {
                that.isShowCamera = true
            },
            fail: function (res) {
                console.log('' + res)
                uni.showModal({
                    title: '请求授权您的摄像头',
                    content: '如需正常使用此小程序功能,请您按确定并在设置页面授权用户信息',
                    confirmText: '确定',
                    success: (res) => {
                        if (res.confirm) {
                            uni.openSetting({
                                success: function (res) {
                                    console.log('成功')
                                    console.log(res)
                                    if (res.authSetting['scope.camera']) {
                                        //设置允许获取摄像头
                                        console.log('设置允许获取摄像头')
                                        uni.showToast({
                                            title: '授权成功',
                                            icon: 'success',
                                            duration: 1000,
                                        })
                                        that.isShowCamera = true
                                    } else {
                                        //不允许
                                        uni.showToast({
                                            title: '授权失败',
                                            icon: 'none',
                                            duration: 1000,
                                        })
                                        uni.navigateBack({ delta: 1 })
                                    }
                                },
                            })
                        } else {
                            //取消
                            uni.showToast({
                                title: '授权失败',
                                icon: 'none',
                                duration: 1000,
                            })
                            uni.navigateBack({ delta: 1 })
                        }
                    },
                })
            },
        })
    },
    methods: {
        //拍照
        takePhotoAction() {
            this.ctx.takePhoto({
                quality: 'high', //高质量
                success: (res) => {
                    const tempFilePath = res.tempImagePath
                    this.loadTempImagePath(tempFilePath)
                },
                fail(error) {
                    console.log(error)
                },
            })
        },
        // 打开相册
        async takeAlbumAction() {
            let tempFilePath = await this.chooseImage()
            if (tempFilePath) {
                this.loadTempImagePath(tempFilePath)
            }
        },
        loadTempImagePath(options) {
            var that = this
            uni.getSystemInfo({
                success: function (res) {
                    // px与rpx之间转换的公式:px = rpx / 750 * uni.getSystemInfoSync().windowWidth;
                    // 矩形的位置
                    // var image_x = 0;
                    // var image_y = 0;
                    // var image_width = that.data.windowWidth;
                    // var image_height = that.data.windowHeight
                    var image_x = (36 / 750) * uni.getSystemInfoSync().windowWidth //起始点
                    var image_y = (400 / 750) * uni.getSystemInfoSync().windowWidth
                    var image_width = (680 / 750) * uni.getSystemInfoSync().windowWidth //图片大小
                    var image_height = (280 / 750) * uni.getSystemInfoSync().windowWidth
                    console.log(image_x, image_y, image_width, image_height)
                    uni.getImageInfo({
                        src: options,
                        success: function (res) {
                            that.isShowImage = true
                            that.canvas = uni.createCanvasContext('image-canvas', that)
                            //过渡页面中,图片的路径坐标和大小
                            that.canvas.drawImage(options, 0, 0, that.windowWidth, that.windowHeight)
                            uni.showLoading({
                                title: '数据处理中...',
                                icon: 'loading',
                                duration: 10000,
                            })
                            // 这里有一些很神奇的操作,总结就是MD拍出来的照片规格居然不是统一的过渡页面中,对裁剪框的设定
                            that.canvas.setStrokeStyle('black')
                            that.canvas.strokeRect(image_x, image_y, image_width, image_height)
                            that.canvas.draw()
                            setTimeout(function () {
                                uni.canvasToTempFilePath({
                                    //裁剪对参数
                                    canvasId: 'image-canvas',
                                    x: image_x, //画布x轴起点
                                    y: image_y, //画布y轴起点
                                    width: image_width, //画布宽度
                                    height: image_height, //画布高度
                                    destWidth: image_width, //输出图片宽度
                                    destHeight: image_height, //输出图片高度
                                    success: function (res) {
                                        that.image = res.tempFilePath
                                        //清除画布上在该矩形区域内的内容。
                                        // that.canvas.clearRect(0, 0, that.data.width, that.data.height)
                                        // that.canvas.drawImage(res.tempFilePath, image_x, image_y, image_width, image_height)
                                        // that.canvas.draw()

                                        // 上传图片给后端返回https链接
                                        that.uploadTo(res.tempFilePath)

                                        //生成base64
                                        // uni.getFileSystemManager().readFile({
                                        // 	filePath: res.tempFilePath, //图片路径
                                        // 	encoding: 'base64', //编码格式
                                        // 	success: result => {
                                        // 		//成功的回调
                                        // 		console.log('data:image/png;base64,' + result.data)

                                        // 		//在此可进行网络请求
                                        // 	},
                                        // 	fail: function (e) {
                                        // 		uni.hideLoading()
                                        // 		uni.showToast({
                                        // 			title: '出错啦...',
                                        // 			icon: 'loading',
                                        // 		})
                                        // 	},
                                        // })
                                    },
                                })
                            }, 1000)
                        },
                    })
                },
            })
        },
        async uploadTo(tempFilePath) {
            // 上传图片给后端返回https链接
            let uploadRes = await this.uploadFile(tempFilePath)

            console.log(uploadRes, 'uploadRes')
            if (uploadRes) {
                //图片解析
                const data = await this.getImageData(uploadRes)
                uni.hideLoading()
                //解析之后跳转页面
                this.goToAddRecord(data)
            }
        },
         async chooseImage(count = 1) {
            let _that = this
            //从本地相册选择图片或使用相机拍照。此接口不再更新,
            //建议使用 wx.chooseMedia(拍摄或从手机相册中选择图片或视频)
            let res = await uni.chooseMedia({
                count, //默认9
                mediaType: ['image'],
                sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
                // sourceType: ['album', 'camera'], //从相册选择,使用相机拍摄
                sourceType: ['album'], //从相册选择
            })

            if (res[1]) {
                const filePath = res[1].tempFiles[0].tempFilePath
                // 返回图片地址
                return filePath
            } else {
                return false
            }
        },
        
        async uploadFile(filePath) {
            let _that = this
            let token = await AuthProvider.getAccessToken()
            let resArr = await uni.uploadFile({
                url: _that.$config.UPLOAD_FILE_URL,
                name: 'file',
                filePath,
                header: { Authorization: token },
            })
            if (resArr[0]) {
                console.log('识别图片报错')
                _that.showError(resArr[0].errMsg)
                return false
            } else {
                const res = resArr[1]
                const resData = JSON.parse(res.data)
                if (resData.code == 100) {
                    return resData.data.url
                }
                return false
            }
        },
        getImageData(imgUrl) {
            return getBloodDataApi(imgUrl + '?x-oss-process=image/resize,w_2048,h_2048,m_lfit').then((res) => {
                //无论图片识别成功与否 跳转到添加页面
                this.toastShow = false
                this.noOnShow = false
                const data = { ...res, picUrl: imgUrl }
                return data
            })
        },
        //识别图片,跳转页面
        goToAddRecord(res) {
            const { type } = this.options
            let blood = res.code == 100 ? res.data.bloodSugarNum : '',
                time = '',
                path = '/packageA/pages/record/record'

            if (type === '2') {
                //历史记录
                const addBlood = this.$utils.getStorage('addBlood')
                time =
                    res.code == 100
                        ? this.$date.formatDate(res.data.measurementTime, 'YYYY/MM/DD hh:mm')
                        : addBlood.date + ' ' + addBlood.time + ':00'
            } else {
                //首页//添加血糖页面
                time =
                    res.code == 100
                        ? this.$date.formatDate(res.data.measurementTime, 'YYYY/MM/DD hh:mm')
                        : this.$date.formatDate(new Date(), 'YYYY/MM/DD hh:mm')
            }
            // path = `/packageA/pages/record/record?bloodSugarNum=${blood}&measurementTime=${time}&code=${res.code}&picUrl=${res.picUrl}&type=${type}`
            //血糖存储数据
            const bloodData = {
                bloodSugarNum: blood,
                measurementTime: time,
                code: res.code,
                picUrl: res.picUrl,
                type,
            }
            this.$utils.setStorage('bloodData', bloodData)
            if (type === '1' || type === '2') {
                //关闭photo当前页面,进入record
                uni.redirectTo({
                    url: path,
                }).then(() => {
                    if (type === '2') this.$utils.removeStorage('addBlood')
                })
            } else {
                //记录从当前页面返回添加血糖页面
                this.$utils.setStorage('goBackAdd', true)
                uni.navigateBack({ delta: 1 })
            }
        },
    },
}
</script>

<style lang="scss" scoped>
.camera-box {
     width: 100vw;
     height: 100vh;
}

.camera-box .camerabgImage {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

.camera-box .camerabgImage .active {
    position: absolute;
    top: 400rpx;
    left: 36rpx;
    right: 36rpx;
}

.camera-box .camerabgImage .active-image {
    display: block;
    width: 680rpx;
    height: 280rpx;
}

.camera-box .camerabgImage .text {
    text-align: center;
    margin-top: 56rpx;
    margin-bottom: 240rpx;
    font-size: 28rpx;
    font-weight: 400;
    color: #d9d9d9;
    line-height: 40rpx;
}

.camera-box .camerabgImage .btn {
    width: 110rpx;
    height: 110rpx;
    border-radius: 50%;
    background: #fff;
    border: 6rpx solid#fff;
    margin: 0 auto;
}

.camera-box .camerabgImage .btn .button {
    width: 102rpx;
    height: 102rpx;
    border-radius: 50%;
    border: 4rpx solid#000;
}
.capture_image {
    width: 100%;
    height: auto;
    position: relative;
}
</style>

参考链接: