首页 前端知识 uniapp(vue3)cavans实现电子签名功能

uniapp(vue3)cavans实现电子签名功能

2024-05-25 09:05:24 前端知识 前端哥 281 710 我要收藏

  1. 创建组件

<template>
    <view class="box" v-show="modelValue" :style="{height:'100%'}">
        <view class="whole canvas-autograph flexc">
            <canvas class="scroll-view" canvas-id="mycanvas" @touchstart="touchstart" @touchmove="touchmove"
                disable-scroll="true" @touchend="touchend" />
            <view class="fun-box ">
                <van-button round block type="warning" size="small" @click="clear">
                    清空
                </van-button>
                <van-button round block type="primary" size="small" @click="confirm">
                    确认
                </van-button>
                <van-button round block type="danger" size="small" @click="cancel">
                    取消
                </van-button>
            </view>
        </view>
    </view>
</template>
<script setup>
    //  base64转Blob格式方法
    //  base64转文件流方法
    import {
        parseBlob,
        base64toFile,
        blobToDataURI
    } from '@/utils/base64ToFile.js'
    //  使用七牛云封装的图片上传方法
    import {
        qiniuUploadSubscribe
    } from '@/utils/upload.js'
    import {
        ref,
        reactive,
        watch,
        getCurrentInstance,
        onMounted
    } from 'vue'
    const {
        proxy: t
    } = getCurrentInstance()
    const emits = defineEmits(['update:modelValue', 'complete'])
    const props = defineProps({
        modelValue: {
            type: Boolean,
            default: false
        },
        infor: {
            type: Object,
            default: {}
        },
    })
    watch(() => props.modelValue, e => {}, {
        immediate: true,
    })
    let cavWidth = ref(2000)
    let cavWidth1 = ref(2000)
    let points = reactive([])
    let pointList = ref([])
    const isDraw = ref(false)
    let canvaCtx = reactive(uni.createCanvasContext('mycanvas'))
    canvaCtx.lineWidth = 4;
    canvaCtx.lineCap = 'round'
    canvaCtx.lineJoin = 'round'
    const touchstart = e => {
        let startX = e.changedTouches[0].x
        let startY = e.changedTouches[0].y
        let startPoint = {
            X: startX,
            Y: startY
        }
        points.push(startPoint);
        canvaCtx.beginPath();
    }
    const touchmove = e => {
        let moveX = e.changedTouches[0].x
        let moveY = e.changedTouches[0].y
        let movePoint = {
            X: moveX,
            Y: moveY
        }
        points.push(movePoint)
        pointList.value.push(movePoint)
        let len = points.length
        if (len >= 2) {
            draw()
        }
    }
    const draw = () => {
        let point1 = points[0]
        let point2 = points[1]
        points.shift()
        canvaCtx.moveTo(point1.X, point1.Y)
        canvaCtx.lineTo(point2.X, point2.Y)
        canvaCtx.stroke()
        canvaCtx.draw(true)
    }
    const touchend = e => {
        points = [];
    }
    const clear = () => {
        pointList.value = []
        return uni.getSystemInfo()
            .then(res => {
                canvaCtx.clearRect(0, 0, res.windowWidth, res.windowHeight);
                canvaCtx.draw(true);
                return res
            })
            .catch(err => {
                console.log(err);
            })
    }
    const confirm = () => {
        if (pointList.value.length < 10) {
            uni.showToast({
                icon: 'none',
                title: '请签字'
            })
        } else {
            uni.canvasToTempFilePath({
                    canvasId: 'mycanvas',
                })
                .then(res => {
                    const {
                        tempFilePath
                    } = res
                    getImageInfo(tempFilePath)
                })
        }
    }
    const cancel = () => {
        pointList.value = []
        clear().then((res) => {
            emits('update:modelValue', false);
        })
    }
    const getImageInfo = (src) => {
        const {
            infor: {
                idCard
            }
        } = props
        let lista = {}
        uni.showLoading({
            title: "正在上传"
        })
        uni.getImageInfo({
            src,
            success(res) {
                let img = new Image()
                img.src = res.path
                let canvas = document.createElement('canvas');
                let ctx = canvas.getContext('2d')
                let rate = res.height / res.width
                let width = 300 / rate
                let height = 300
                cavWidth.value = 300 / rate
                cavWidth1.value = 300
                ctx.translate(height / 2, width / 2)
                ctx.rotate((270 * Math.PI) / 180)
                ctx.drawImage(img, -width / 2, -height / 2, width, height)
                canvas.toBlob((fileSrc) => {
                    blobToDataURI(fileSrc, (dataurl) => {
                        const imgInfor = idCard + '/' + new Date().getTime()
                        const blobPath = parseBlob(dataurl)
                        const File = base64toFile(dataurl, imgInfor)
                        File.path = blobPath
                        <!-- qiniuUploadSubscribe(二次封装的上传方法),如果项目上传
                    图片不需要进行二次封装可直接用uni.uploadFile上传 -->
                        qiniuUploadSubscribe({
                            files: [File],
                            type: 5,
                            success: (res, index) => {
                                if (res.code == 20000) {
                                    lista.url = res.data
                                    //  setFilePath(全局定义的设置图片访问路径的方法)
                                    lista.imageURL = t.setFilePath(res.data)
                                    lista.percent = 100
                                    lista.uploadStatus = 'SUCCESS'
                                    lista.size = File.size
                                    lista.type = File.type
                                    lista.name = File.name
                                    lista.path = File.path
                                    //将后端接口返回的图片路径返回给父组件
                                    emits('complete', [lista])
                                }
                                uni.showToast({
                                    icon: 'none',
                                    title: res.message
                                })
                                pointList.value = []
                                uni.hideLoading();
                                cancel()
                            },
                            error: (err, index) => {
                                lista.uploadStatus = 'ERROR'
                            },
                            progress: (res, index) => {
                                const {
                                    progress,
                                    totalBytesSent,
                                    totalBytesExpectedToSend
                                } = res
                                lista.percent = Math.floor(progress)
                                lista.uploadStatus = progress < 100 ? 'UPLOADING' :
                                    'SUCCESS'
                            },
                            complete: (err, index) => {
                                console.log(err, index)
                            },
                        })
                    });
                })
            }
        })
    }
</script>

<style scoped lang="scss">
    .box {
        position: absolute;
        animation: boxBotToTop .9s;
        -webkit-animation: boxBotToTop .9s;
        width: 92%;
        bottom: 0;
        left: 4%;
        z-index: 997;
        background: #374151;
        border-radius: 30rpx;
    }

    @keyframes boxBotToTop {
        0% {
            opacity: 0;
            -webkit-transform: translateY(40px);
            transform: translateY(40px);
        }

        100% {
            opacity: 1;
            -webkit-transform: translateY(0);
            transform: translateY(0) scale(.9);
        }
    }

    @-webkit-keyframes boxBotToTop {
        0% {
            opacity: 0;
            -webkit-transform: translateY(40px);
            transform: translateY(40px);
        }

        100% {
            opacity: 1;
            -webkit-transform: translateY(0);
            transform: translateY(0) scale(.9);
        }
    }

    .canvas-autograph {
        position: absolute;
        z-index: 998;
        height: 95%;
        width: 82%;
        top: 50%;
        left: 50%;
        transform: translate(-43%, -50%);

        .scroll-view {
            width: 100%;
            height: 100%;
            background-color: #FFFFFF;
        }

        .fun-box {
            position: absolute;
            display: flex;
            align-items: center;
            width: 100%;
            justify-content: space-between;
            transform: rotate(90deg);
            top: 50%;
            left: -59%;

            .fun-box-btn {
                width: 160rpx;
                height: 100%;
                color: #FFFFFF;
                border-radius: 20rpx;
                border: 1rpx solid #C0C0C0;
                text-align: center;

                +.fun-box-btn {
                    margin-left: 20rpx;
                }
            }
        }

    }
</style>
  1. 组件调用

<template>
    <view class="homePage">
        <view style="position: absolute;height: 100vh;bottom:0;width:100%" v-if="isCanvas">
            <MiliuAutograph v-model="isCanvas" @complete="complete" :infor="{idCard:floatingForm.idCard}" />
        </view>
    </view>
</template>
<script setup>
    import MiliuAutograph from '@/components/MiliuAutograph/index.vue'
    import {
        ref,
        defineComponent,
        getCurrentInstance,
        reactive
    } from 'vue'
    const {
        proxy: t
    } = getCurrentInstance()
    const isCanvas = ref(false)
    const complete = e => {
           console.log(e,'电子签名图片上传成功后,后端返回的图片路径');
    }
</script>

转载请注明出处或者链接地址:https://www.qianduange.cn//article/9434.html
标签
评论
会员中心 联系我 留言建议 回顶部
复制成功!