微信小程序可以通过canvas实现手写签名的效果,本文中使用的是微信小程序Canvas 2D接口
本示例中绘制的是横屏签名的效果,效果图如下:

这里我们需要调整canvas的物理宽高,默认物理宽高为300*150px,物理宽高调整通过css样式即可,本文中需要根据屏幕高度进行动态调整,使用的是行内样式
页面布局:

<template><view class="sign-page" :style="{paddingTop: top + 'px'}"><view class="canvas-box"><view class="left-pane"><view class="f28 text-gray6 left-text">请签字确认</view><view class="right-box"><view class="left-button" @click="clearContext"><text class="ic ic-delete text-gray6"></text><text class="f30 text-gray6 ml5">清空</text></view><button class="right-button" @click="confirm">完成</button></view></view><!-- canvas的物理宽高可通过样式调整 --><canvasclass="canvas"disable-scroll type="2d" id="myCanvas"@touchstart="handleTouchstart"@touchmove="handleTouchmove":style="{width: canvasWidth + 'px', height: canvasHeight + 'px'}"></canvas><view class="right-pane"><view class="dis-flex back-button" @click="back"><text class="ic ic-left text-gray6"></text><text class="text-gray6 ml15">取消</text></view><view class="title"><text class="text text-gray6">{{title || '检测人员'}}</text></view></view></view><canvasclass="canvas2"disable-scroll type="2d" id="myCanvas2":style="{width: canvasHeight + 'px', height: canvasWidth + 'px'}"></canvas></view>
</template>

js代码:canvas的物理宽高调整后,canvas的逻辑宽高也需要进行调整,默认逻辑宽高是300*150px,(小程序Canvas 2D接口支持修改逻辑宽高),具体参考本文中的initCanvas方法


<script>export default {data() {return {canvasWidth: 300,canvasHeight: 150,top: 0,canvas: null,title: ''}},onLoad() {const menuData = uni.getMenuButtonBoundingClientRect()uni.getSystemInfo({success: (res) => {let navPadding = menuData.top - res.statusBarHeight// 顶部高度 = 状态栏高度 + 胶囊按钮行高度 + 胶囊按钮上下的paddinglet navHeight = res.statusBarHeight + navPadding * 2 + menuData.height// 设置canvas的物理宽高this.canvasWidth = res.windowWidth - 100this.canvasHeight = res.windowHeight - navHeight - 20this.top = navHeight}})},onReady() {this.initCanvas()},methods: {initCanvas() {uni.createSelectorQuery().select('#myCanvas').fields({ node: true, size: true }).exec((res) => {// 修改canvas的逻辑宽高// 如果不修改canvas的逻辑宽高,仅通过样式修改canvas的宽高,会导致绘图时比例不对,// 如将物理宽度改为600,但逻辑宽度还是300,假设画图时的起点x是100,那么实际看到的绘图起点是200const canvas = res[0].nodethis.canvas = canvasthis.ctx = canvas.getContext('2d')// canvas.width = this.canvasWidth// canvas.height = this.canvasHeight// 注意:按照上面方式调整,虽然逻辑宽高和物理宽高保持一致了,但是会发现画出来的线会有锯齿不够清晰// 因为不同设备上物理像素与逻辑像素是不一致的// 因此canvas的逻辑宽高等于物理宽高分别*dprconst dpr = wx.getSystemInfoSync().pixelRatiocanvas.width = this.canvasWidth * dprcanvas.height = this.canvasHeight * dpr// 假设dpr等于2,,那么canvas的物理宽度是600,逻辑宽度就是1200,// 假设画图时的起点x是100,那么实际看到的绘图起点是50,此时只需要将绘图内容进行等比例放大即可this.ctx.scale(dpr, dpr)})},handleTouchstart(e) {this.lineBegin(e.touches[0].x, e.touches[0].y)},handleTouchmove(e) {this.lineTo(e.touches[0].x, e.touches[0].y)},lineBegin(x, y) {this.ctx.beginPath()// 新版Canvas 2D接口,直接修改属性即可this.ctx.lineCap = 'round'this.ctx.lineWidth = 5this.startX = xthis.startY = ythis.ctx.moveTo(this.startX, this.startY)},lineTo(x, y) {this.ctx.lineTo(x, y)this.ctx.stroke()this.ctx.moveTo(x, y)},clearContext() {this.ctx.clearRect(0, 0, this.canvasWidth, this.canvasHeight)},confirm() {uni.canvasToTempFilePath({canvas: this.canvas, success: (res) => {this.rotateImage(res.tempFilePath)}})},// 横屏签名,但是canvas的方向是垂直的,导出的图片也是竖屏,需要将图片进行旋转rotateImage(filePath) {uni.createSelectorQuery().select('#myCanvas2').fields({ node: true, size: true }).exec((res) => {// 首先绘制一个宽高与上面canvas相反的canvasconst canvas = res[0].nodethis.canvas2 = canvasthis.ctx2 = canvas.getContext('2d')const dpr = wx.getSystemInfoSync().pixelRatiocanvas.width = this.canvasHeight * dprcanvas.height = this.canvasWidth * dprthis.ctx2.scale(dpr, dpr)// 绘制上述导出的签名图片到新的canvas上const img = this.canvas2.createImage()img.src = filePathimg.onload = () => {// 签名图片旋转绘画解析在下方this.ctx2.translate(0, this.canvasWidth);this.ctx2.rotate(270 * Math.PI / 180)this.ctx2.drawImage(img, 0, 0, this.canvasWidth, this.canvasHeight)uni.canvasToTempFilePath({canvas: this.canvas2, success: (res) => {this.handleUploadFile(res.tempFilePath)}}) }                        })},handleUploadFile(filePath) {uni.uploadFile({url: config.requestUrl + '/biz/file/upload/annex', filePath,name: 'file',header: {'Authorization': getToken()},success: (res) => {// 调用接口成功if(res.statusCode == 200) {// 解析服务器返回数据const data = JSON.parse(res.data)if(data.code == 200) {const responseUrl = config.requestUrl + data.filePathconst eventChannel = this.getOpenerEventChannel()eventChannel.emit('getSignImage', {filePath: responseUrl, fileId: data.fileId});this.back()}} else {uni.hideLoading()}},fail: (res) => {uni.hideLoading()}})},back() {uni.navigateBack()}}}
</script>

由于签名的方向是横向的,但是canvas本身是竖向,导出的签名图片也为竖向,那么我们需要将导出的图片旋转为横向后重新绘制到canvas上然后导出。签名图旋转绘制的效果图如下:

图中黑色部分为canvas区域,竖向的签名图片为刚刚我们导出的图片,绘制到canvas上的效果如下图,如果我们要将其横向绘制到面板上,此时需要将绘画内容沿左上角顺时针旋转270deg,此时可以发现旋转后图片的覆盖区域在canvas向上移动canvasWdth的位置,那么旋转前将canvas的绘画起点重置到(0,canvasWidth)即可保证绘画内容旋转后刚好覆盖在canvas上

需要注意的点是,后面绘画旋转后的canvas在实际页面中我们是不需要看到的,需要通过样式将其隐藏,如果需要使用canvasToTempFilePath方法导出图片的话,不能使用display:none的隐藏canvas,否则会报错no image found,
可以通过定位和visiblity(opacity)属性隐藏。

页面样式:

<style lang="scss" scoped>.sign-page {min-height: 100vh;background-color: #f5f5f5;.canvas-box {position: relative;width: 100%;}.left-pane {width: 100rpx;.left-text {position: absolute;top: 0;line-height: 100rpx;transform: translateX(100rpx) rotate(90deg) ;transform-origin: 0 0;}.right-box {position: absolute;display: flex;align-items: center;bottom: 0;transform: translateX(100rpx) rotate(90deg)  translateX(-100%) translateX(100rpx);transform-origin: 0 0;.left-button {line-height: 100rpx;margin-right: 30rpx;}.right-button {font-size: 30rpx;color: #fff;width: 140rpx;height: 60rpx;line-height: 60rpx;background-color: green;}}}.canvas {margin: 0 auto;background-color: #fff;border: 2rpx dashed #d9d9d9;transform-origin: center center;}.canvas2 {/*设置display:none会导致wx.canvasToTempFilePath报错no image found*//*display: none;*/position: absolute;opacity: 0;}.right-pane {position: absolute;width: 100rpx;height: 100%;right: 0;top: 0;.back-button {position: relative;z-index: 5;white-space: nowrap;line-height: 100rpx;align-items: center;transform: translateX(100rpx) rotate(90deg);transform-origin: 0 0;}.title {position: absolute;top: 0;z-index: 4;width: 100rpx;height: 100%;white-space: nowrap;display: flex;justify-content: center;align-items: center;line-height: 100rpx;text-align: center;.text {display: inline-block;transform: rotate(90deg);}}}}
</style>

微信小程序canvas实现简易手写签名版(uni-app)相关推荐

  1. 微信小程序—写字板、手写签名(高仿毛笔效果)让汉字引领世界

    摘要 计算机的发明让手写受到毁灭性打击,但手写的经典不能埋没,这是一款手写签名工具,根据手写速度计算笔宽,很有毛笔的风韵,请拿去使用. 效果 体验 体验途径:画布系列>写字板 代码 js Pag ...

  2. 微信小程序Canvas实现手写签名

    微信小程序Canvas实现手写签名 功能描述 点击按钮显示弹窗,弹窗主体为签名板,底部两个按钮为清除和保存. 清除按钮:清空签名板 保存按钮:保存签名为图片,并关闭弹窗 关键点分析 Canvas实现手 ...

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

    微信小程序canvas实现签名功能 在微信小程序项目中,开发模块涉及到手写签名功能,微信小程序canvas闪亮登场 文章目录 微信小程序canvas实现签名功能 前言 一.微信小程序canvas实现签 ...

  4. 【微信小程序canvas】实现小程序手写板用户签名(附代码)

    [微信小程序canvas]实现小程序手写板用户签名(附代码) 工作中公司业务需要的微信小程序用户签字功能 先看效果图: wxml <view class="wrapper"& ...

  5. 微信小程序 canvas type = 2d 绘制海报心得(包括怎么绘制图片和圆角图片和圆角矩形等)

    微信小程序 canvas type=2d 使用心得 为了方便这里我封装成了一个component 然后说说怎么使用最新的方法(使用方法类似于html中的canvas可以进行参考)获取--canvas ...

  6. 微信小程序Canvas卡顿优化解决方法

    文章目录 一.引入 二.分析问题 三.解决方法 四.解决后效果图 五.绘制好的地图 一.引入 原安卓图书馆选座项目CSDN博客链接: Android图书馆选座系统课程设计 最近在搞微信小程序,想把以前 ...

  7. 微信小程序--放入个性化手绘地图具体步骤(腾讯地图)

    微信小程序–放入个性化手绘地图具体步骤(腾讯地图) 前言:小程序中想要实现个性化手绘地图需要通过H5嵌入的模式进行实现. 1.首先需要一个腾讯地图的账号(微信登录即可),然后选择个性化地图进入(htt ...

  8. mpvue 微信小程序canvas生成海报

    mpvue 微信小程序canvas生成海报 效果 贴代码 html <template><!--index.wxml--><view class="poster ...

  9. 用python画圆角矩形_详解微信小程序canvas圆角矩形的绘制的方法

    详解微信小程序canvas圆角矩形的绘制的方法 发布时间:2020-10-04 18:20:31 来源:脚本之家 阅读:103 作者:清夜 微信小程序允许对普通元素通过 border-radius 的 ...

最新文章

  1. buuctf N种方法解决
  2. 计算机应用发表论文,计算机应用论文发表.docx
  3. Sharepoin学习笔记—架构系列—Sharepoint服务(Services)与服务应用程序框架(Service Application Framework) 1
  4. 【算法系列之四】柱状图储水
  5. python实现拆分、合并、删除pdf
  6. vb6 枚举对象属性
  7. linux回到桌面的命令符_三 基本的base shell 命令
  8. 台积电股价涨势如虹,将带领台股挑战历史新高!
  9. vba有下拉框的模糊查找_巧用数据验证制作模糊匹配的下拉列表
  10. SpringMVC 工作流程
  11. 《21天学通Java(第7版)》—— 2.7 总结
  12. 熵权法 算权重系数 python
  13. MathCAD14破解版
  14. python怎么读取txt数据_对python .txt文件读取及数据处理方法总结
  15. VM虚拟机上的网络设置
  16. python如何调用pyd_C#调用pyd的方法
  17. luci网页shell_Luci框架-LUA的一个web框架使用
  18. max7456 C语言,用于MAX7456随屏显示器SPI接口的C程序
  19. 解决win7 若要安装Office2010,需要在计算机上安装MSXML版本6.10.1129.0 问题
  20. inno setup 自定义生成的卸载程序

热门文章

  1. 计算机辅助药物设计课程,计算机辅助药物设计课程.doc
  2. 完美日记90分钟卖1个亿,网红营销,只要学会这3招!
  3. javaEE学习总结
  4. 嵌入式Linux学习入门
  5. 《B端产品经理必修课》读书笔记 (第一章)
  6. 做了几个Firefox的主题
  7. 211本科大佬的真实面试经历:测试人要不要去外包公司?
  8. everything文件快速搜索工具
  9. 蓝桥杯准备(Python)罗马数字
  10. 微信内置浏览器第三方网页分享链接给朋友以及转发到朋友圈无链接图片和链接描述的问题