微信小程序canvas实现签名功能

canvas实现签名功能

        作为一个开发小白,在查找了网上的一堆资料后最终决定使用canvas来实现签名功能,点击签名按钮后弹出弹框签名,签名后点击保存成图片转成base64后上传到后端,现在将将相关经验分享出来,如有问题请斧正相互学习,谢谢~

页面代码

        <view class="title-level2"><text class="text-bold2">负责人签名:</text></view>
        <view class="weui-cell__bd" style="padding-bottom: 150px;">
            <view class="state_line signed">
                <image class="temp_img" wx:if="{{concatSignUrl.length > 0}}" src="{{concatSignUrl}}" />
                <button bindtap="onPopupOpen" class="clean-button" wx:if="{{concatSignUrl.length > 0}}" bindtap="onPopupOpen">重置签名</button>
                <!-- <view class="ma_r20 colorBlue" wx:else bindtap="onPopupOpen">{{ lineTitle }}</view> -->
                <button class="centered-button" wx:else bindtap="onPopupOpen">签名</button>
                <!-- 签名 start -->
                <van-popup custom-class="signed_popup" lock-scroll="{{ true }}" show="{{ showPopupc }}" closeable="true" catchtouchmove="true" bind:close="onPopupClose">
                    <view class="top_view">签名区域</view>
                    <view class="cont_view">
                        <canvas class="canvastyle" type="2d" id='canvasId' bindtouchstart="bindtouchstart" bindtouchmove="bindtouchmove">
                        </canvas>
                    </view>
                    <view class="foot_view">
                        <text class="reset" bindtap="clear">重置</text>
                        <text class="confirm" bindtap="export">确定</text>
                    </view>
                </van-popup>
                <!-- 签名 end -->
            </view>
        </view>

点击签名,弹出弹窗,同时在每次打开时初始化画板

    onPopupOpen() {
        var that = this
        that.setData({
            showPopupc: true,
        })
        setTimeout(function () {
            that.initialize();
            that.delayedClear();
        }, 200)
    },

初始化画板  

    initialize() {
        wx.createSelectorQuery()
            .select('#canvasId')
            .fields({
                node: true,
                size: true
            })
            .exec((res) => {
                // Canvas 对象
                const canvas = res[0].node
                // 渲染上下文
                const ctx = canvas.getContext('2d')
                // Canvas 画布的实际绘制宽高
                const width = res[0].width
                const height = res[0].height

                // 初始化画布大小
                const windowInfo = wx.getSystemInfoSync()
                const dpr = windowInfo.pixelRatio
                const dprW = width * dpr
                const dprH = height * dpr
                canvas.width = dprW
                canvas.height = dprH
                ctx.scale(dpr, dpr)
                // 设置线条宽度
                ctx.lineWidth = 3; // 这里可以调整线条的宽度,单位是像素
                this.setData({
                    canvas: canvas,
                    ctxContext: ctx,
                    ctxWidth: width,
                    ctxHeight: height,
                    ctxDpr: dpr
                })
            })
    },

签名画线

    bindtouchstart(e) {
        this.data.ctxContext.moveTo(e.changedTouches[0].x, e.changedTouches[0].y)
    },
    bindtouchmove(e) {
        this.setData({
            flagMove: true
        })
        this.data.ctxContext.lineTo(e.changedTouches[0].x, e.changedTouches[0].y);
        this.data.ctxContext.stroke();
        this.data.ctxContext.moveTo(e.changedTouches[0].x, e.changedTouches[0].y);
    },

真机签名实测 


清除画板代码

    delayedClear() {
        var that = this;
        setTimeout(function () {
            that.clear(); // Clear the canvas after a short delay
        }, 50);
    },
    clear() {
        var w = this.data.ctxWidth
        var h = this.data.ctxHeight
        this.data.ctxContext.clearRect(0, 0, w, h)
        this.data.ctxContext.beginPath()
        this.setData({
            flagMove: false
        })
    },

将图片上传到后端保存转成base64

    export () {
        const that = this;
        if (!that.data.flagMove) {
            wx.showToast({
                duration: 3000,
                title: '请您先签名',
                icon: 'none'
            })
            return;
        }
        // 生成图片
        wx.canvasToTempFilePath({
            canvas: that.data.canvas,
            success: res => {
                const tempFilePath = res.tempFilePath

                that.setData({
                    concatSignUrl: tempFilePath,
                    showPopupc: false
                })
                // 将图片转为 Base64
                that.imageToBase64(tempFilePath, function (error, base64String) {
                    if (error) {
                        console.error('Base64 转换失败', error);
                        return;
                    }
                    // 上传 Base64 编码的图片
                    that.uploadImg(base64String);
                });
            },
        })
    },
    imageToBase64(tempFilePath, callback) {
        wx.getFileSystemManager().readFile({
            filePath: tempFilePath,
            encoding: 'base64',
            success: function (res) {
                // 拼接与 PC 端一致的格式
                var base64Str = "data:image/svg+xml;base64," + res.data;
                callback(null, base64Str);
            },
            fail: function (error) {
                callback(error);
            }
        });
    },
uploadImg(base64) {
    var _this = this;
        const params = {
            base64: base64,
        };// 对象传参
        request.POST('miniapp/miniappUploadBase64', params, function (res) {
            if (res.data && res.data.code === 0) {
                _this.setData({
                    signFile: res.data.fileName,
                });
            } else {
                wx.hideToast();
                //app.showErrorModal(res.data.msg, '修改失败');
            }
        }, function (res) {
            wx.hideToast();
            //app.showErrorModal(res.msg, '修改失败');
        });
    },

部分样式代码

.centered-button{
    background-color: #1ab394;
    color: #fff;
    margin-top: 20px; 
    margin-left: auto;
    margin-right: auto;
    margin-bottom: auto;
    border-radius: 20px;
}
.clean-button{
    background-color: rgb(241, 80, 80);
    margin-top: 10px; 
    margin-left: auto;
    margin-right: auto;
    margin-bottom: auto;
    color: white;
    border-radius: 20px;
}
/* 签名样式 */
.signed .temp_img {
    cursor: pointer;
    width: 98%;
    height: 200rpx;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid rgb(107, 107, 107);  /* 添加边框 */
    margin: auto;  /* 水平居中 */
    margin-top: 10px;  /* 调整图片靠下的距离,可以根据需要调整值 */
    border-radius: 10px;  /* 设置边框为圆角,可以根据需要调整半径 */
}
  .signed .signed_popup {
    display: flex;
    flex-direction: column;
    position: fixed;
    width: 100%;
    height: 500rpx;
    border-radius: 50rpx;
  }
  
  .signed_popup .top_view {
    text-align: center;
    height: 100rpx;
    line-height: 100rpx;
    font-size: 32rpx;
    font-weight: 500;
  }
  .signed_popup .fullImg {
    position: absolute;
    top: 30rpx;
    right: 40rpx;
    width: 40rpx;
    height: 40rpx;
  }
  .signed_popup .cont_view {
    flex: 1;
    margin: 0 40rpx 30rpx;
  }
  .signed_popup .canvastyle {
    width: 100%;
    height: 100%;
    background: #F7F8FA;
  }
  .signed_popup .foot_view {
    display: flex;
    height: 100rpx;
    border-top: 1rpx solid #EBEDF0;
  }
  .signed_popup .reset {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    font-size: 38rpx;
    color: #323233;
    border-right: 1rpx solid #EBEDF0;
  }
  .signed_popup .confirm {
    display: flex;
    align-items: center;
    justify-content: center;
    flex: 1;
    font-size: 38rpx;
    color: #1483FE;
  }

出现的问题

在微信开发者工具中测试画板时,会出现偏移的问题,但是在真机上面就没有,可能是微信接口问题,还有就在微信开发者工具中可以正常使用签名画板,但是在手机上面没有出现可以使用微信开发者工具中的详情,里面的调试基础库,推送到自己的手机上面,再次运行就可以正常签名。其次也可以发布到体验版上面测试,也是可以正常签名的

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值