小程序实现电子签名(wepy@1.7)

公司业务需要实现电子签名功能,当前我使用的是wepy框架。

html

<template>
    <view class="wrap">
        <view class="content-wrap" id="content">
            <canvas class='myCanvas' canvas-id="myCanvas" @touchmove='move' @touchstart='start' @touchend='end' @touchcancel='cancel' @longtap='tap' disable-scroll='true' @error='error'></canvas>
        </view>
        <view class="bottom-wrap">
            <view class="delete-btn" @tap="clearClick">清除</view>
            <view class="paint-brush">
                <view class="thickness">
                    <repeat for="{{thicknessArr}}" index="index" item="item">
                        <text class="{{item}} {{activeIndex == index ? 'active':''}}" @tap="thicknessChange({{item}}, {{index}})"></text>
                    </repeat>
                </view>
                <view class="paint-color">
                    <repeat for="{{paintColorArr}}" index="index" item="item">
                        <text class="{{item.className}}" @tap="selectColor({{item.color}})"></text>
                    </repeat>
                </view>
                <view class="done" @tap="saveClick">完成</view>
            </view>
        </view>
    </view>
</template>

less

page {
    width: 100%;
    height: 100%;
    background: #fff;
}

.wrap {
    width: 100%;
    height: 100%;
    border-top: 1px solid #d5d5d5;
    box-sizing: border-box;
}

.content-wrap {
    width: 100%;
    height: calc(100% - 84rpx);
    .myCanvas {
        width: 100%;
        height: 100%;
    }
}

.bottom-wrap {
    width: 100%;
    height: 80rpx;
    overflow: hidden;
    color: #333;
    border-top: 1px solid #0068b1;
    .delete-btn {
        float: left;
        height: 80rpx;
        line-height: 80rpx;
        padding: 0 15rpx;
        font-size: 28rpx;
    }
    .paint-brush {
        float: right;
        height: 80rpx;
        line-height: 80rpx;
        overflow: hidden;
        .thickness {
            float: left;
            height: 80rpx;
            line-height: 80rpx;
            margin-right: 25rpx;
            text {
                display: inline-block;
                border: 1px solid #333;
                border-radius: 50%;
                margin: 0 15rpx;
                vertical-align: middle;
            }
            .small {
                width: 14rpx;
                height: 14rpx;
            }
            .medium {
                width: 22rpx;
                height: 22rpx;
            }
            .large {
                width: 30rpx;
                height: 30rpx;
            }
            .active {
                background: blue;
            }
        }
        .paint-color {
            float: left;
            text {
                display: inline-block;
                width: 54rpx;
                height: 54rpx;
                border-radius: 12rpx;
                margin: 12rpx 15rpx;
            }
            .red {
                background: red;
            }
            .blue {
                background: blue;
            }
            .black {
                background: #333;
            }
        }
        .done {
            float: left;
            height: 80rpx;
            line-height: 80rpx;
            padding: 0 15rpx;
            font-size: 28rpx;
        }
    }
}

ts

import wepy from 'wepy';
import { connect } from 'wepy-redux';
import { uploadSignature } from '@/store/actions/index';

@connect({
    userMeta: (state) => state.globle.userMeta,                    // 用户数据
    signInfo: (state) => state.seals.signInfo,                     // 上传返回的签章信息
}, {
    uploadSignature,                                               // 上传签章
})

export default class ElectronicSignature extends wepy.page {

    config = {
        navigationBarTitleText: '手写签名',
        pageOrientation: 'landscape',                             // 手机横屏展示
    };

    data = {
        thicknessArr: ['small', 'medium', 'large'],                // 画笔粗细
        activeIndex: 0,                                            // 画笔当前粗细的key
        paintColorArr: [                                           // 画笔颜色数组
            { className: 'red', color: '#ff0000' },
            { className: 'blue', color: '#0c00ff' },
            { className: 'black', color: '#000000' },
        ],
        signImage: '',                                              // 生成的图片地址
        canvasContent: null,                                        // 画布
        canvasw: 0,                                                 // 画布的宽
        canvash: 0,                                                 // 画布的高
        touchs: [],                                                 // 所有坐标位置
    };

    methods = {
        uploadSignature,
        // 画布触摸开始触发
        start: (event) => {
            // 获取触摸开始的 x,y
            this.touchs.push({
                x: event.changedTouches[0].x,
                y: event.changedTouches[0].y,
            });
        },
        // 画布的触摸移动手势响应
        move: (event) => {
            this.touchs.push({
                x: event.touches[0].x,
                y: event.touches[0].y,
            });
            if (this.touchs.length >= 2) {
                this.methods.draw(this.touchs);
            }
        },
        draw: (touchs) => {
            const point1 = touchs[0];
            const point2 = touchs[1];
            touchs.shift();
            this.canvasContent.moveTo(point1.x, point1.y);
            this.canvasContent.lineTo(point2.x, point2.y);
            this.canvasContent.stroke();
            this.canvasContent.draw(true);
        },
        // 选择笔的粗细
        thicknessChange: (type, index) => {
            this.activeIndex = index;
            this.methods.clearClick();  // 清除画布
            switch (type) {
                case 'small':
                    this.canvasContent.setLineWidth(2);
                    break;
                case 'medium':
                    this.canvasContent.setLineWidth(4);
                    break;
                case 'large':
                    this.canvasContent.setLineWidth(6);
                    break;
            }
        },
        // 选择画笔颜色
        selectColor: (color) => {
            this.methods.clearClick();  // 清除画布
            this.canvasContent.setStrokeStyle(color);
        },
        clearClick: () => {
            // 清除画布
            this.canvasContent.clearRect(0, 0, this.canvasw, this.canvash);
            this.canvasContent.draw(true);
        },
        async saveClick() {
            wepy.showLoading({title: '上传中...'});
            // 把当前画布指定区域的内容导出生成指定大小的图片
            const imgResult = await wepy.canvasToTempFilePath({ canvasId: 'myCanvas' });
            const imgPath = imgResult.tempFilePath;
            // 获取生成的图片大小
            const fileInfo = await wepy.getFileInfo({ filePath: imgPath });
            const imgSize = fileInfo.size;
            // 上传
            this.methods.uploadSignature({
                path: imgPath,
                keyName: 'signature_file',
                params: { fileLength: imgSize, userId: this.userMeta.uuid },
            });
        },
        backPrevPage: () => {
            wepy.navigateBack({
                delta: 1,
            });
        },
        // 画布的触摸取消响应
        cancel: (event) => {
            // console.log('触摸取消' + event);
        },
        // 画布的长按手势响应
        tap: (event) => {
            // console.log('长按手势' + event);
        },
        error: (event) => {
            // console.log('画布触摸错误' + event);
        },
        // 画布的触摸移动结束手势响应
        end: (event) => {
            // 清空轨迹数组
            for (const item of this.touchs) {
                this.touchs.pop();
            }
        },
    };

    onLoad() {
        // 获得Canvas的上下文
        this.canvasContent = wepy.createCanvasContext('myCanvas');
        // console.log(this.canvasContent);
        // 设置线的颜色
        this.canvasContent.setStrokeStyle('#000000');
        // 设置线的宽度
        this.canvasContent.setLineWidth(2);
        // 设置线两端端点样式更加圆润
        this.canvasContent.setLineCap('round');
        // 设置两条线连接处更加圆润
        this.canvasContent.setLineJoin('round');
        // 获取画布宽高
        const self = this;
        const query = wx.createSelectorQuery();
        query.select('#content').boundingClientRect(res => {
          self.canvasw = res.width;
          self.canvash = res.height;
        }).exec();
    }

    watch = {
        signInfo(val) {
            val && wepy.showToast({title: '保存签名成功!', icon: 'success'});
        },
    };
}

 

posted @ 2019-11-09 09:23  顾非白  阅读(3034)  评论(0编辑  收藏  举报