电子签名生成的图片为空白,以及生成透明底签名图片转为白色底

博客围绕电子签名展开,介绍了两个问题的解决方法。一是生成图片为空白的问题,需在 draw() 回调异步调用 uni.canvasToTempFilePath 接口;二是透明底签名图片转为白色底,尝试多种方法后,发现要传入正确宽高,若宽高动态,需在设置底色前获取。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

电子签名如何解决生成的图片为空白的问题,以及生成透明底签名图片转为白色底

一、生成的图片为空白

项目有个新需求需要加电子签名,在实现的过程中遇到了许多问题,现用的插件笔画延迟非常严重,好不容易做完之后又得换一个插件;换了之后又发现画完图后产生的图片是空白的,百度之后才知道,生成图片调用的 uni.canvasToTempFilePath 接口必须要在 draw()回调使用
并且需要异步调用,在图片生成好之后再将它上传到服务器上,否则上传之后回显的图片就是空白的。
在 useCanvans.js 文件里

// 生成图片调用的uni.canvasToTempFilePath接口必须要在draw()回调使用,
// 否则可能生成空白图片,异步方法保证等待图片完成了再上传到服务器
function saveCanvas() {
  return new Promise((resolve, rej) => {
    params.ctx.draw(
      true,
      createFileUrl().then((res) => {
        resolve(res);
      })
    );
  });
}

function createFileUrl() {
  return new Promise((resolve, rej) => {
    uni.canvasToTempFilePath({
      canvasId: 'handWriting',
      fileType: 'png',
      quality: 1, //图片质量
      success(res) {
        console.log(res.tempFilePath, 'canvas生成图片地址');
        resolve(res.tempFilePath);
      },
      fail: function (err) {
        console.log('图片生成失败:' + err);
      },
    });
  });
}

在需要调用生成图片 api 的文件里异步调用:

      saveCanvas().then((res) => {
        console.log(
          '%c [ tempFilePath ]',
          'font-size:13px; background:pink; color:#bf2c9f;',
          res
        );
        wx.uploadFile({...});
      });
二、透明底签名图片转为白色底

第一次尝试
使用第二个插件中,有一个函数的注释说明转背景为白色,但是引入这个插件后生成的图片却还是透明的

  		onLoad() {
			this.ctx = uni.createCanvasContext("handWriting");
			this.$nextTick(() => {
				uni.createSelectorQuery().select('.handCenter').boundingClientRect(rect => {
						this.canvasWidth = rect.width;
						this.canvasHeight = rect.height;
						/* 将canvas背景设置为 白底,不设置  导出的canvas的背景为透明 */
						this.setCanvasBg('#fff');
					})
					.exec();
			});
		},


    			//设置canvas背景色  不设置  导出的canvas的背景为透明
			//@params:字符串  color
			setCanvasBg(color) {

				/* 将canvas背景设置为 白底,不设置  导出的canvas的背景为透明 */
				//rect() 参数说明  矩形路径左上角的横坐标,左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
				//这里是 canvasHeight - 4 是因为下边盖住边框了,所以手动减了写
				this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);
				// ctx.setFillStyle('red')
				this.ctx.setFillStyle(color);
				this.ctx.fill(); //设置填充
				this.ctx.draw(); //开画
			}

第二次尝试
一开始还以为是我理解错了,上面那个方法不是转白色底方法,于是又去网上找了其他方法:使用 wx.canvasGetImageData 和 wx.canvasPutImageData 改变图片的底色。

function toWhite() {
  console.log(
    '%c [ width ]',
    'font-size:13px; background:pink; color:#bf2c9f;'
  );
  wx.canvasGetImageData({
    canvasId: 'handWriting',
    x: 0,
    y: 0,
    width: params.canvasWidth,
    height: params.canvasHeight,
    success(res) {
      console.log(res.width); // 100
      console.log(res.height); // 100
      console.log(res.data instanceof Uint8ClampedArray); // true
      console.log(res.data.length); // 100 * 100 * 4
      var imageData = res.data;
      for (var i = 0; i < imageData.length; i += 4) {
        // 当该像素是透明的,则设置成白色
        if (imageData[i + 3] === 0) {
          imageData[i] = 255;
          imageData[i + 1] = 255;
          imageData[i + 2] = 255;
          imageData[i + 3] = 255;
        }
      }
      wx.canvasPutImageData({
        canvasId: 'handWriting',
        x: 0,
        y: 0,
        width: params.canvasWidth,
        height: params.canvasHeight,
        data: imageData,
        success(res) {
          console.log(
            '%c [ toWhite ]',
            'font-size:13px; background:pink; color:#bf2c9f;',
            res
          );
        },
      });
    },
  });
}

尝试过后发现还是不行,调试的错误信息显示传入的 width 为 0,这才发现前面获取宽高失败了,于是写死传入的宽高尝试了一下,发现还是不可以,但是让我想明白了为什么第一次尝试失败,也是因为在 setCanvasBg 函数中传入的宽高为 0。

this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);

传入正确的宽高之后果然成功了,但是要注意如果宽高是动态的话,一定要在设置底色前将宽高获取,否则生成的第一张签名还是透明底。
但是还是不明白为什么在初始化时获取宽高失败,很可能是由于this.$nextTick内的代码没有成功执行。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值