微信小程序使用 canvas 实现手写签名

在使用微信小程序开发中,有的需求场景中会需要用户手写签名、或者绘制一些路径,通常会使用 canvas 来实现这种需求

在小程序的开发官方文档中我们可以查找到相关的 canvas 接口使用方法,在文档中我们看到微信官方的提示

2.9.0 起支持一套新 Canvas 2D 接口(需指定 type 属性),同时支持同层渲染,原有接口不再维护。相关api:获取 canvas 实例

而官方文档中的说明也确实是旧版的 canvas 文档,那么在本文中将详细介绍一下新版和旧版的 canvas 绘制签名的方法

在本例中,使用了小程序的开发框架 mpxmpx 使用的是微信小程序原生的标签和语法,因此,可以直接将代码复制到项目中进行使用。

使用旧版的 Canvas 接口

介绍一下如何使用旧版的小程序 canvas 接口

  1. 首先在页面中添加一个 canvas 容器,并添加上相应的时间监听和处理函数
   <view class="main">
     <canvas canvas-id="custom-canvas" class="canvas" bindtouchstart="onStart" bindtouchmove="onMove" bindtouchend="onEnd"></canvas>
   </view>

需要注意的是:此处不能在 canvas 的元素中添加 type=“2d”,如果添加了该属性,则小程序将会把此 canvas 解析为新版本的 canvas2D

  1. 在脚本中添加处理函数

    <script>
    import { createPage } from '@mpxjs/core'
    let ctx
    
    createPage({
      data: {},
      methods: {
        onStart(e) {
          console.log(e)
          const [touch] = e.touches
          const { x, y } = touch
          ctx.moveTo(x, y)
        },
        onMove(e) {
          const [touch] = e.touches
          const { x, y } = touch
          const point = { x, y }
          this.draw(point)
        },
        draw(point) {
          ctx.lineTo(point.x, point.y)
          ctx.stroke()
          ctx.draw(true)
          ctx.moveTo(point.x, point.y)
        },
        onEnd() {
          console.log('Draw end')
        },
        init() {
          ctx = wx.createCanvasContext('custom-canvas', this)
          ctx.setStrokeStyle('#00ff00')
          // 设置线的宽度
          ctx.setLineWidth(5)
          // 设置线两端端点样式更加圆润
          ctx.setLineCap('round')
          // 设置两条线连接处更加圆润
          ctx.setLineJoin('round')
        }
      },
      onLoad() {
        this.init()
      }
    })
    </script>
    

    此处需要注意的是:

    • 由于不需要将 canvas 的实例在模板中使用,因此此处将 ctx 声明为了局部变量

    • 使用旧版的 canvas 接口,我们可以将初始化过程放在页面挂载的 onLoad 事件中,在初始化过程中通过 wx.createCanvasContext方法创建 canvas 实例,使用框架的时候需要将 this 值作为第二个参数传入 wx.createCanvasContext 方法中,否则获取不到 canvas 的实例

    • touchstart 事件开始的时候,我们需要获取到触摸的起始位置,也就是通过事件中的 touches,该属性返回点击的位置数组,此时我们将 canvas 的起始位置设置到点击位置

      const [touch] = e.touches
      const { x, y } = touch
      ctx.moveTo(x, y)
      
    • 在处理绘制事件的时候,我们一定要按照 lineTo() > stroke() > draw() > moveTo() 的方式来绘制,有的同学就会说了,为什么要再添加一个 moveTo() 呢?我们以动图表现一下0-0

      没有使用 moveTo()的情况:

      图中可以看出如果我们移动的过快,就会出现虚线的点

      添加了 moveTo()的效果:

    • 该旧版接口目前微信小程序已经不再继续维护了,但是如果要适配 v2.9.0 之前的微信版本基础库的话,就需要使用旧版的接口了

  2. 设置画布的大小,此处我设置了整个屏幕的大小

    <style lang="stylus">
    .canvas {
      width 100vw
      height 100vh
      background-color red
    }
    </style>
    

使用新版的 canvas

微信小程序中新版的 canvas 是基于 Web 标准的 canvas2D 来做渲染的,因此相关的接口文档可以从 MDN 中的 canvas2D 章节中来查看

下面就介绍一下如何使用 canvas2D 来实现签名

<view class="wrapper">
       <canvas
         wx:ref="SIGNATURE"
         class="signature"
         disable-scroll="{{true}}"
         bindtouchstart="onStart"
         bindtouchmove="onMove"
         bindtouchend="onEnd"
         bindtap="oMouseDown"
         type="2d"
       >
       </canvas>
     </view>

注意:此处的 canvas 容器添加了 type="2d" 属性,来声明使用的是新版的 canvas2D
2. 实例化 canvas 实例

   import { createPage } from '@mpxjs/core'
	   let context
	   
	   createPage({
	     data: {
	       listData: ['手机', '电视', '电脑']
	     },
	     properties: {
	       orders: Array
	     },
	     methods: {
	       /**
	        * 绘制签名
	        */
	       onStart(e) {
	         console.log(e)
	         const [touch] = e.touches
	         const { x, y } = touch
	         context.moveTo(x, y)
	       },
	       onMove(e) {
	         const [touch] = e.touches
	         const { x, y } = touch
	         const point = { x, y }
	         this.draw(point)
	       },
	       cancel(e) {},
	       tap(e) {},
	       error(e) {},
	       onEnd(e) {
	         this.triggerEvent('signature-touch-end')
	       },
	       draw(point) {
	         context.lineTo(point.x, point.y)
	         context.stroke()
	         context.moveTo(point.x, point.y)
	       },
	       init() {
	         this.$refs.SIGNATURE.node((result) => {
	           const canvas = result.node
	           context = canvas.getContext('2d')
	           const { windowHeight, windowWidth, pixelRatio: dpr } = wx.getSystemInfoSync()
	           canvas.width = windowWidth * dpr
	           canvas.height = windowHeight * dpr
	           context.strokeStyle = 'red'
	           context.lineWidth = 5
	           context.fillStyle = 'rgba(255, 255, 255, 0)'
	           context.scale(dpr, dpr)
	         }).exec()
	       }
	     },
	     ready() {
	       this.init()
	     }
	   })

对以上代码做一下简单说明:

  • 由于 canvas2D 的实例需要获取到 canvas 的容器元素,因此我们最早只能在页面 onReady 中调用初始化函数,如果在 onLoad 或者 onShow 中调用该函数,则无法获取到 canvas 容器元素

  • 初始化函数中的 this.$refs.SIGNATUREmpx 对小程序的获取元素方法 wx.createSelectorQuery()的包装,因此这里完全可以使用小程序原生的方法获取到 canvas 容器

  • canvas2D 的使用需要显式的设置宽和高,小程序中的 canvas 默认为 300 * 150的大小,因此在这里我首先获取了整个可用屏幕的大小,然后适配为设备屏幕的 dpr,并对画布进行缩放,这样会对 canvas 的展示效果具体到每一个像素,这也是终极画布的奥秘

  • 触摸开始的时候和旧版的canvas 接口是一样的,需要 moveTo 到起始点

  • 在 canvas2D 绘制的时候和旧版的 canvas 不同:canvas2D 只需要 lineTo() > stroke() > moveTo() 即可,不需要显式的调用 draw() 方法,如下图动图中显式的效果,要不旧版的 canvas 更为细腻

  1. 设置画布容器的宽高

    .wrapper {
      width 100vw
      height 100vh
      display flex
      justify-context center
      align-items center
    }
    .signature {
      width 100vw
      height 100vh
      margin:0 auto
    }
    

注意:此处设置的 canvas 元素的宽高和实例化 canvas 时候的宽和高不一样,这里可以认为仅仅只是一个容器,而实例中的宽和高才是画布的宽高

其他

canvas2D 和 小程序的 canvas 旧版接口中,还提供了清除画布、生成图片等方法,在本文中我们仅展示画布的绘制部分,想要做更深功能的话可以查阅相关文档即可

 ![](https://img-blog.csdnimg.cn/img_convert/2e0ca51d2474d4e2772d3b391ce79f8a.gif)

更多内容

前端开发转全栈,目前的技术栈是 Node.js、Python,日常研究 C、C++ 和 Rust,孜孜啃食系统开发和网络设计中~

更多的内容请移步GitHub@ruxf,知乎@如小非,掘金@如小非,或者关注我的公众号@全栈开发师,欢迎来撩~

学到老,写到老,生命不停,编程不止~

加油,打工人~

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
是的,微信小程序可以使用Canvas实现签名功能。具体实现方法如下: 1. 在wxml文件中添加一个canvas元素: ```html <canvas canvas-id="myCanvas" style="width: 100%; height: 100%;" bindtouchstart="touchStart" bindtouchmove="touchMove" bindtouchend="touchEnd"></canvas> ``` 2. 在js文件中定义相关的变量和函数: ```javascript // 定义画布上下文 let context = null; // 定义画笔颜色和粗细 let penColor = "#000000"; let penWidth = 2; // 定义画笔是否正在使用 let isPainting = false; // 定义画笔起始点位置 let lastX = 0; let lastY = 0; // 获取画布上下文 context = wx.createCanvasContext("myCanvas"); // 触摸开始函数 function touchStart(event) { isPainting = true; lastX = event.touches[0].x; lastY = event.touches[0].y; } // 触摸移动函数 function touchMove(event) { if (isPainting) { let currentX = event.touches[0].x; let currentY = event.touches[0].y; context.beginPath(); context.moveTo(lastX, lastY); context.lineTo(currentX, currentY); context.setStrokeStyle(penColor); context.setLineWidth(penWidth); context.stroke(); context.closePath(); lastX = currentX; lastY = currentY; context.draw(true); } } // 触摸结束函数 function touchEnd() { isPainting = false; } ``` 3. 在wxml文件中添加按钮来保存签名: ```html <button type="primary" bindtap="save">保存</button> ``` 4. 在js文件中定义保存签名的函数: ```javascript // 保存签名函数 function save() { wx.canvasToTempFilePath({ canvasId: "myCanvas", success: function(res) { wx.saveImageToPhotosAlbum({ filePath: res.tempFilePath, success(res) { wx.showToast({ title: "保存成功", icon: "success", duration: 2000 }); }, fail(res) { wx.showToast({ title: "保存失败", icon: "none", duration: 2000 }); } }); }, fail: function (res) { console.log(res); } }); } ``` 这样就可以在微信小程序实现签名功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mrmengj

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值