uniapp使用Canvas实现电子签名

news2025/1/16 15:43:13

来源:

公司的一个需求,需要给新注册的会员和客商需要增加签署协议功能;

之前的思路:
1、使用vue-signature-pad来实现电子签名,但是安卓手机不兼容;
2、uniapp插件市场来实现,但是对HBuilderX的版本有要求,无奈公司只能使用3.4.7版本;

前面2种思路都不行那就用Canvas来实现

Canvass

canvas 是 html 的一个标签,它可以结合 JavaScript 提供的 canvasApi 来绘制各种各样的图形。canvas 主要用于绘制 2D 图形。注意:当你不设置 canvas 的宽高时,它的默认宽高是 300px、150px。

需要实现的功能如图:
在这里插入图片描述

代码实现

EctronicSignature.vue

<template>
  <view class="ectronic-signature">
    <canvas
      class="board-canvas"
      canvas-id="drawCanvas"
      disable-scroll="true"
      @touchstart="touchStart"
      @touchmove="touchMove"
      @touchend="touchEnd"
    ></canvas>
    <view class="btn">
      <u-button type="success" @click="saveImage" text="保存" class="btnItem"></u-button>
      <u-button @click="clearDrawBoard" text="清空" class="btnItem"></u-button>
    </view>
  </view>
</template>

<style lang="scss" scoped>
……
</style>
EctronicSignature.ts

 curDrawArr: any = [];
  startX: any = 0;
  startY: any = 0;
  ctx: any = {};
  begin: Boolean = false;
  bgColor: String = 'white'; //背景色
  lineWidth: Number = 4; //画笔宽度
  penMode: Boolean = true; //打开画笔  开关
  currentTab: any = 1;
  currentIndex: any = 0;
  selectPointer: any = []; //所有选中的线
  cache: any = '';
  points: any = [];

  onReady() {
    this.ctx = uni.createCanvasContext('drawCanvas', this); // 获取canvas上下文对象 vue的写法是先获取,之后通过.getContext("2d")来获取上下文
    this.cache = new Map(); // 缓存
    this.ctx.setLineWidth(this.lineWidth); // 设置画笔的粗细
  }

  // ctx.draw()绘制结果呈现在canvas
  // isReverse: 是否保留之前的像素
  draw(isReverse = false, cb) {
    this.ctx.draw(isReverse, () => {
      if (cb && typeof cb == 'function') {
        cb();
      }
    });
  }

  // 绘画 开始
  touchStart(e) {
    console.log('绘画开始', e.touches[0].x, e.touches[0].y);
    // customPrint('我能够进行绘制');
    if (this.penMode) {
      this.lineBegin(e.touches[0].x, e.touches[0].y);
      this.lineAddPoint(e.touches[0].x, e.touches[0].y);
      this.draw(true, ''); // 呈现画面
    }
    this.points.push([e.touches[0].x, e.touches[0].y]); // 存储绘制的点
    this.selectPointer.push([[e.touches[0].x, e.touches[0].y]]);
  }

  // 开始绘制线条
  lineBegin(x, y) {
    this.begin = true; // 作为一个标记代表开始绘画
    this.ctx.beginPath(); // 开始创建一个路径
    this.startX = x;
    this.startY = y;
    this.ctx.moveTo(this.startX, this.startY); // 将路径移动到画布中的指定点
    this.lineAddPoint(x, y); // 绘制线条中间添加
  }

  // 绘画 移动
  touchMove(e) {
    console.log('绘画移动', e.touches[0].x, e.touches[0].y);

    if (this.begin) {
      if (this.penMode) {
        this.lineAddPoint(e.touches[0].x, e.touches[0].y);
        this.draw(true, '');
      }
      this.points.push([e.touches[0].x, e.touches[0].y]);
      this.selectPointer[this.selectPointer.length - 1].push([e.touches[0].x, e.touches[0].y]);
    }
  }

  // 绘制线条中间添加点
  lineAddPoint(x, y) {
    this.ctx.moveTo(this.startX, this.startY);
    this.ctx.lineTo(x, y); // 增加一个新的点,然后创建一条从上次指定点到目标点的线
    this.ctx.stroke(); // 画出当前路径的边框
    this.startX = x;
    this.startY = y;
  }

  // 绘画 结束
  touchEnd(e) {
    if (this.penMode) {
      // this.curDrawArr = [];
      this.points = [];
      this.lineEnd();
    }
  }

  // 绘制线条结束
  lineEnd() {
    this.ctx.closePath(); // 关闭一个路径,关闭路径会连接起点和终点
    this.begin = false;
  }

  // 检验画布是否为空
  isCanvasBlank(canvas) {
    const blank = document.createElement('canvas'); //系统获取一个空canvas对象
    blank.width = canvas.width;
    blank.height = canvas.height;
    return canvas.toDataURL() == blank.toDataURL();  // .toDataURL()将canvas对象转换为base64位编码
  }

  // 保存 图片数据
  saveImage() {
    const _this = this;
    uni.canvasToTempFilePath({
      canvasId: 'drawCanvas',
      success: function(res) {
        console.log('res ==>', res);
        // 在H5平台下,tempFilePath 为 base64
        // this.uploadimage(res.tempFilePath,"save",page.currentTab)
        const canvas = document.getElementsByTagName('canvas')[0];
        if (_this.isCanvasBlank(canvas)) {
          uni.showToast({
            title: '请签字!!!',
            icon: 'none',
          });
          return false;
        }
      },
    });
  }

   //清除
  clearDrawBoard() {
    this.ctx.draw();
    this.selectPointer = [];
  }
  }

推荐资料

https://www.runoob.com/html/html5-canvas.html
https://uniapp.dcloud.net.cn/component/canvas.html#canvas
https://open.dingtalk.com/document/personalapp/setlinewidth

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1218321.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年09月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 以下选项中,不是tkinter变量类型的是?( ) A: IntVar() B: StringVar() C: DoubleVar() D: FloatVar() 答案:D tkinter 无 FloatVar()变量类型。 第2题 关于tkinter,以下说…

web3资讯及远程工作

各位如果想了解区块链相关的消息可以通过如下网址了解&#xff0c;里面还会有相关职位招聘&#xff08;包括远程工作&#xff09;&#xff0c;还可以在里面进行发帖&#xff0c;进入即可获得1000积分&#xff0c;后期可以兑换一些礼品Cryptosquare

小型机房380V断电报警门磁开关状态检测远程控制RTU

在现代社会中&#xff0c;小型机房起到了至关重要的作用&#xff0c;为各种系统和设备提供稳定的电力供应。然而&#xff0c;由于各种原因&#xff0c;如供电故障、设备故障或非法侵入等&#xff0c;机房的正常运行可能会受到威胁。为了保障机房的安全和可靠性&#xff0c;我们…

Java GUI实现五子棋游戏

五子棋是一种双人对弈的棋类游戏&#xff0c;通常在棋盘上进行。棋盘为 1515 的方格&#xff0c;黑白双方各执棋子&#xff0c;轮流在棋盘的格点上落子&#xff0c;先在横、竖、斜线上形成五个相连的同色棋子者获胜。五子棋规则简单&#xff0c;易学难精&#xff0c;兼具攻防和…

疑似openAI的BUG

Chat gpt 4.0 『最新数据2023年』 Chat gpt 3.5 智商不在线『最近数据2021年9月左右』 发现了疑似openAI的一个bug 通过固定连接访问就可以用chatgpt4.0 4.0版本的费用为20美金一个月 https://chat.openai.com/?modelgpt-4-gizmo

03-关系和非关系型数据库对比

关系和非关系型数据库对比 关系型数据库(RDBMS)&#xff1a;MySQL、Oracl、DB2、SQLServer 非关系型数据库(NoSql)&#xff1a;Redis、Mongo DB、MemCached 插入数据结构的区别 传统关系型数据库是结构化数据,向表中插入数据时都需要严格的约束信息(如字段名,字段数据类型,字…

GO语言的由来与发展历程

Go语言&#xff0c;也称为Golang&#xff0c;是由Google公司的Robert Griesemer、Ken Thompson和Rob Pike三个大牛于2007年开始设计发明&#xff0c;并于2009年正式对外发布的开源编程语言。 三名初始人的目标是设计一种适应网络和多核时代的C语言&#xff0c;Go语言从C继承了…

简单回顾矩阵的相乘(点乘)230101

[[1 0 1][1 1 0]] [[3 0 0 3][2 2 1 3][1 3 1 1]] [[4. 3. 1. 4.][5. 2. 1. 6.]]乘以 c11 a11*b11 a12*b21 a13*b31 1*3 0*2 1*1 4 c12 a11*b12 a12*b22 a13*b32 1*0 0*2 1*3 3 c13a11*b13 a12*b23a13*b33 c14a11*b14 a12*b24a13*b34 c21a21*b11 a22*b21 a23*b…

windows11编译ffmpeg

安装msys2&#xff0c;直接https://www.msys2.org/上下载exe安装即可&#xff0c;默认路径&#xff1b; 选择msys2-mingw64启动&#xff0c;将下载源替换为中科大 sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirrorlist*pacman -S…

免费的快速手机文件解压APP,快冲

各位小伙伴们大家好&#xff0c;今天我要介绍一款手机上必备的神奇工具&#xff01;你有没有经常遇到需要解压文件情况呢&#xff1f;还在为不知道用哪个软件而烦恼吗&#xff1f;别担心&#xff0c;我给你带来了解决方案 &#xff0c;就是这一款免费的解压精灵。 解压精灵是一…

git撤销未git commit的文件

目录 一、问题描述 二、方式1&#xff1a;git命令撤销&#xff08;更专业&#xff09; 1、文件已git add&#xff0c;未git commit 2、本地修改&#xff0c;未git add &#xff08;1&#xff09;撤销处于unstage的文件&#xff0c;即删除已有变动 &#xff08;2&#xff…

C语言查找幸运数字(ZZULIOJ1056:幸运数字)

题目描述 小明对某些数字有偏爱&#xff0c;例如&#xff0c;他喜欢7的倍数&#xff0c;而不喜欢4的倍数&#xff0c;如果一个整数是7的倍数&#xff0c;而不是4的倍数&#xff0c;小明会认为这个数字是他的幸运数字。现在给定两个整数m和n&#xff0c;请你帮小明找m到n范围内的…

C++初阶 类和对象(下)

目录 一、拷贝构造函数 1.1 什么是拷贝构造函数&#xff1f; 1.2 为什么得是引用&#xff1f; 1.3 使用拷贝构造函数 1.4 拷贝构造函数有什么用&#xff1f; 二、运算符重载 2.1 什么是运算符重载&#xff1f; 2.2 尝试前须知 2.3 常见运算符重载 2.3.1运算符重载 …

vs2017打开工程提示若要解决此问题,请使用以下选择启动 Visual Studio 安装程序: 用于 x86 和 x64 的 Visual C++ MFC

下载 error MSB8036: 找不到 Windows SDK 版本8.1。请安装所需的版本的 Windows SDK 或者在项目属性页中或通过右键单击解决方案并选择“重定解决方案目标”来更改 SDK 版本。 error&#xff1a;D8016 “/ZI”和“/Gy-”命令行选项不兼容 ”问题解决

Maven项目指定main方法配置

例如有个maven工程 打包后 xxx.jar 而这个maven工程里可能有很多main方法,比如测试的main方法 插件指定 <build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId>&…

2023数维杯国际赛数学建模竞赛选题建议及B题思路讲解

大家好呀&#xff0c;2023年第九届数维杯国际大学生数学建模挑战赛今天早上开赛啦&#xff0c;在这里先带来初步的选题建议及思路。 目前团队正在写B题和D题完整论文&#xff0c;后续还会持续更新哈&#xff0c;大家三连关注一下防止迷路。 注意&#xff0c;本文只是比较简略…

dvwa 文件上传漏洞通关攻略

dvwa 文件上传漏洞通关攻略 文章目录 dvwa 文件上传漏洞通关攻略low等级mediumhighimpossible 练习文件上传漏洞的攻击与防御 low等级 点击文件上传进行测试上传个一句话木马 <?php eval($_REQUEST[777]);?>上传成功 访问上传路径 进行蚁剑连接 代码审计 <?ph…

AOF是什么?

目录 一、AOF是什么&#xff1f; 二、使用AOF 三、命令写入 四、重写机制 4.1 触发AOF 4.2 AOF执行流程 一、AOF是什么&#xff1f; AOF是Append Only File&#xff0c;是Redis中实现持久化的一种方式。以独⽴⽇志的⽅式记录每次命令&#xff0c;重启时再重新执⾏ AOF ⽂件中的…

创邻科技亮相ISWC 2023,国际舞台见证知识图谱领域研究突破

近日&#xff0c;第22届国际语义网大会 ISWC 2023 在雅典希腊召开&#xff0c;通过线上线下的形式&#xff0c;聚集了全球的顶级研究人员、从业人员和行业专家&#xff0c;讨论、发展和塑造语义网和知识图谱技术的未来。创邻科技CEO张晨博士作为知识图谱行业专家受邀参会&#…

SystemVerilog学习(8)——包的使用

目录 一、包的定义 二、导出包的内容 1、可以通过域的索引符::号直接引用 2、可以指定索引一些需要的包中定义的类型到指定的容器中 3、通过通配符*来将包中所有的类别导入到指定容器中 三、包的使用 在进行本文的学习之前&#xff0c;首先需要对SV中类相关的内容有充分的认识…