uni-app开发的canvas签名组件(多个签名并处理调用接口)

1、首先把签字板的组件放在compunents下指定位置

<template>
    <view v-if="visibleSync" class="cat-signature" :class="{'visible':show}">
        <view class="mask" @tap="close" />
        <view class="content">
            <canvas class='firstCanvas' :canvas-id="canvasId" @touchmove='move' @touchstart='start($event)' @touchend='end'
             @touchcancel='cancel' @longtap='tap' disable-scroll='true' @error='error' />
            <view class="btns">
                <button class="btn" size="mini" type="warn" @click="clear">清除</button>
                <button class="btn" size="mini" type="primary" @click="save">保存</button>
            </view>
        </view>
    </view>
</template>

<script>
    var content = null;
    var touchs = [];
    var canvasw = 0;
    var canvash = 0;
    //获取系统信息
    uni.getSystemInfo({
        success: function(res) {
            canvasw = res.windowWidth;
            canvash = canvasw * 9 / 16;
        },
    })
    export default{
        props:{
            visible: {
                type: Boolean,
                default: false
            },
            canvasId:{
                type: String,
                default: 'firstCanvas'
            }
        },
        data(){
            return{
                show:false,
                visibleSync: false,
                signImage:'',
                hasDh:false,
            }
        },
        watch:{
            visible(val) {
                this.visibleSync = val;
                this.show = val;
                this.getInfo()
            }
        },
        
        created(options) {
            this.visibleSync = this.visible
            this.getInfo()
            setTimeout(() => {
                this.show = this.visible;
            }, 100)
        },
        methods:{
            getInfo(){
                //获得Canvas的上下文
                content = uni.createCanvasContext(this.canvasId,this)
                //设置线的颜色
                content.setStrokeStyle("#000")
                //设置线的宽度
                content.setLineWidth(6)
                //设置线两端端点样式更加圆润
                content.setLineCap('round')
                //设置两条线连接处更加圆润
                content.setLineJoin('round')
            },
            // 
            close() {
                this.show = false;
                this.hasDh = false;
                this.$emit('close')
            },
            // 画布的触摸移动开始手势响应
            start(e){
                let point = {
                    x: e.touches[0].x,
                    y: e.touches[0].y,
                }
                touchs.push(point);
                this.hasDh = true
            },
            // 画布的触摸移动手势响应
            move: function(e) {
                let point = {
                    x: e.touches[0].x,
                    y: e.touches[0].y
                }
                touchs.push(point)
                if (touchs.length >= 2) {
                    this.draw(touchs)
                }
            },
            
            // 画布的触摸移动结束手势响应
            end: function(e) {
                //清空轨迹数组
                for (let i = 0; i < touchs.length; i++) {
                    touchs.pop()
                }
            
            },
            
            // 画布的触摸取消响应
            cancel: function(e) {
                // console.log("触摸取消" + e)
            },
            
            // 画布的长按手势响应
            tap: function(e) {
                // console.log("长按手势" + e)
            },
            
            error: function(e) {
                // console.log("画布触摸错误" + e)
            },
            
            //绘制
            draw: function(touchs) {
                let point1 = touchs[0]
                let point2 = touchs[1]
                // console.log(JSON.stringify(touchs))
                content.moveTo(point1.x, point1.y)
                content.lineTo(point2.x, point2.y)
                content.stroke()
                content.draw(true);
                touchs.shift()
                
            },
            //清除操作
            clear: function() {
                //清除画布
                content.clearRect(0, 0, canvasw, canvash)
                content.draw(true)
                // this.close()
                this.hasDh = false;
                this.$emit('clear')
            },
            save(){
                var that = this;
                if(!this.hasDh){
                    uni.showToast({title:'请先签字',icon:'none'})
                    return;
                }
                uni.showLoading({title:'生成中...',mask:true})
                setTimeout(()=>{
                    uni.canvasToTempFilePath({
                        canvasId: this.canvasId,
                        success: function(res) {
                            that.signImage = res.tempFilePath;
                            that.$emit('save',res.tempFilePath);
                            uni.hideLoading()
                            that.hasDh = false;
                            that.show = false;
                        },
                        fail:function(err){
                            console.log(err)
                            uni.hideLoading()
                        }
                    },this)
                },100)
            }
        }
    }
</script>

<style lang="scss">
    .cat-signature.visible {
        visibility: visible
    }
    .cat-signature{
        display: block;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        overflow: hidden;
        z-index: 11;
        height: 100vh;
        visibility: hidden;
        .mask{
            display: block;
            opacity: 0;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, .4);
            transition: opacity .3s;
        }
        .content{
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            bottom:0;
            right: 0;
            margin: auto; 
            width:94%;
            height: 500upx;
            background: #fff;
            border-radius: 8upx;
            box-shadow: 0px 3px 3px #333;
            // canvas
            .firstCanvas {
                background-color: #fff;
                width: 100%;
                height: 400upx;
            }
            // canvas
            .btns{
                padding: 0 15px;
                height: 100upx;
                overflow: hidden;
                position: absolute;
                bottom: 10upx;
                left: 0;
                right: 0;
                margin: auto;
                display: flex;
                justify-content: space-between;
                .btn{
                    width: 40%;
                    text-align: center;
                    font-size: 28upx;
                    height:60upx;
                    line-height: 60upx;
                    color: #fff;
                    margin-top: 20upx;
                }
            }
        }
    }
    
    .visible .mask {
        display: block;
        opacity: 1
    }
</style>

页面内使用方法如下:

<view class="contract-page-section__input" @click="signature" id="bSign1"><image class="signature-img" :src="contractForm.bSign1" mode="heightFix"></image></view>
<view class="contract-page-section__input" @click="signature" id="bSign2"><image class="signature-img" :src="contractForm.bSign2" mode="heightFix"></image></view>
<canvas-signature :canvas-id="activeSignId" @close="canvasShow = false" @save="signatureSave" :visible="canvasShow" ></canvas-signature>

import canvasSignature from '@/components/canvas-signature/canvas-signature.vue'
components:{canvasSignature},
data() {
            return {
                oneForm:{
                    bSign1: '',
                    bSign2: ''
                },
                // 签字数据
                activeSignatureId:'',
                canvasShow: false
            };
        },
methods:{
            // 获取签字板
            signature(e){
                this.activeSignatureId = e.currentTarget.id
                this.canvasShow = true
            },
            signatureSave(val){
                this.canvasShow = false;
                this.oneForm[this.activeSignatureId] = val
            },
                        async submitHander(){
                            let submitForm = JSON.parse(JSON.stringify(this.oneForm))
                submitForm.bSign1 = await this.base64Transform('bSign1')
                            // 因为转base64位是异步操作,所以使用async、await去实现会方便,多少个签名都可以做,本人的页面10多个签名
                            // 这里考虑尽量深拷贝一个新对象取操作,在返回当前页才不会修改submitForm里的相对路径
                            // 然后就可以使用submitForm作为接口请求的入参
                        },
                        // 签名转base64位文件流
            base64Transform(name){
                return new Promise((resolve, reject)=>{
                    const savedFilePath = this.oneForm[name] //相对路径
                    const path = plus.io.convertLocalFileSystemURL(savedFilePath) //绝对路径
                    const fileReader = new plus.io.FileReader()
                    fileReader.readAsDataURL(path)
                        fileReader.onloadend = (res) => { //读取文件成功完成的回调函数
                            resolve(res.target.result)
                        }
                })
            }
        }

有问题请留言,有可优化的地方也请多多指教

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,431评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,637评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,555评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,900评论 1 318
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,629评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,976评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,976评论 3 448
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,139评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,686评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,411评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,641评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,129评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,820评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,233评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,567评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,362评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,604评论 2 380

推荐阅读更多精彩内容

  • 这是这个系列的第二篇,第一篇介绍了如何配置。这一篇介绍Java与C如何相互介绍。 没有配置过的可以去看看Andro...
    arvinljw阅读 1,281评论 0 2
  • 一、什么是webpack,为什么使用它? 1.1 什么是webpack? webpack是一个模块打包工具,在开发...
    wave浪儿阅读 560评论 0 1
  • 前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,...
    BetterChen阅读 1,955评论 0 3
  • 大家好,我是小编大野宰。 大家是不是很诧异今天的作者怎么那么多? 这是我们密谋了很久的一篇「会客厅」文章,特意在五...
    曹将阅读 2,065评论 1 3
  • 文档维护者:孙尊路 喜欢的话,记得star 一下噢! 适用场景 前些阵子,写了一篇《日历组件实现》的使用在线文档,...
    sunzunlu阅读 2,510评论 0 1