当前位置 博文首页 > 微信小程序实现简单手写签名组件的方法实例

    微信小程序实现简单手写签名组件的方法实例

    作者:dawnlion 时间:2021-09-06 19:01

    目录
    • 背景:
    • 需求:
    • 效果
    • 一、思路
    • 二、实现
      • 1. 页面与样式
      • 2. 初始化
      • 3. 点击时
      • 4. 签名时
    • 三、总结

      背景:

      在做项目过程中,需要在微信小程序中实现手写签名组件。在网上找了微信小程序手写签名实现,但是都是不太理想。在实际运用中,会因为实时计算较多的贝塞尔曲线而产生卡顿。效果不理想。所以退一步,不需要笔锋以及笔迹模拟效果。只需要简单的手写签名实现。

      需求:

      可以实现用户在微信小程序上手写签名。

      需要组件化。

      效果

      一、思路

      在微信小程序中,我们使用canvas组件实现。将用户的输入想象成为一只笔。我们要画的签名是由很多点构成的。但是单纯的点是不能很好地构成线。点与点之间还要由线连接。下面是实现过程代码。

      二、实现

      1. 页面与样式

      wxml

      这里的canvas组件是最新的用法。

      <view class="dashbox">
        <view class="btnList">
          <van-button size="small" bind:click="clearCanvas">清空</van-button>
        </view>
        <view class="handCenter">
          <canvas 
            class="handWriting" 
            disable-scroll="{{true}}" 
            
            bindtouchstart="scaleStart"
            bindtouchmove="scaleMove" 
            bindtouchend="scaleEnd"
            bindtap="mouseDown"
            type="2d"
          >
          </canvas>
        </view>
      </view>
      

      wxss

      .btnList{
          width: 95%;
          margin:0 auto;
      }
      .handWriting{
          background: #fff;
          width: 95%;
          height: 80vh;
          margin:0 auto
      }
      

      2. 初始化

      由于是在自定义组件中使用,所以要注意获取canvas的时候的this指向问题。如果不调用SelectorQuery的In方法,那么就在自定义组件获取不到canvas,因为这个时候指向的父组件。

      Component({
       /**
       * 组件的初始数据
       */
          data: {
              canvasName:'#handWriting',
              ctx:'',
              canvasWidth:0,
              canvasHeight:0,
              startPoint:{
                  x:0,
                  y:0,
              },
              selectColor: 'black',
              lineColor: '#1A1A1A', // 颜色
              lineSize: 1.5,  // 笔记倍数
              radius:5,//画圆的半径
          }, 
          ready(){
              let canvasName = this.data.canvasName;
              let query = wx.createSelectorQuery().in(this);//获取自定义组件的SelectQuery对象
              query.select(canvasName)
              .fields({ node: true, size: true })
              .exec((res) => {
                const canvas = res[0].node;
                const ctx = canvas.getContext('2d');
                //获取设备像素比
                const dpr = wx.getSystemInfoSync().pixelRatio;
                //缩放设置canvas画布大小,防止笔迹错位
                canvas.width = res[0].width * dpr;
                canvas.height = res[0].height * dpr;
                ctx.scale(dpr, dpr);
                ctx.lineJoin="round";
                this.setData({ctx});
              });
        
              query.select('.handCenter').boundingClientRect(rect => {
                  console.log('rect', rect);
                  this.setData({
                      canvasWidth:rect.width,
                      canvasHeight:rect.height
                  });
              }).exec();
          },
         //省略以下代码......
      });
      

      3. 点击时

      Component({
       //省略以上代码...
       methods: {
                  scaleStart(event){
                      if (event.type != 'touchstart') return false;
                      let currentPoint = {
                          x: event.touches[0].x,
                          y: event.touches[0].y
                      }
                      this.drawCircle(currentPoint);
                      this.setData({startPoint:currentPoint});
                },
                  drawCircle(point){//这里负责点
                      let ctx = this.data.ctx;
                      ctx.beginPath();
                      ctx.fillStyle = this.data.lineColor;
                  //笔迹粗细由圆的大小决定
                      ctx.arc(point.x, point.y, this.data.radius, 0 , 2 * Math.PI);
                      ctx.fill();
                      ctx.closePath();
                },
                //省略以下代码...
       }
      })
      

      4. 签名时

      Component({
        //省略以上代码
        methods:{
       drawLine(sourcePoint, targetPoint){
                  let ctx = this.data.ctx;
                  this.drawCircle(targetPoint);
                  ctx.beginPath();
                  ctx.strokeStyle = this.data.lineColor;
                  ctx.lineWidth = this.data.radius * 2;//这里乘2是因为线条的粗细要和圆的直径相等
                  ctx.moveTo(sourcePoint.x, sourcePoint.y);
                  ctx.lineTo(targetPoint.x, targetPoint.y);
                  ctx.stroke();
                  ctx.closePath();
                },
                clearCanvas(){//清空画布
                  let ctx = this.data.ctx;
                  ctx.rect(0, 0, this.data.canvasWidth, this.data.canvasHeight);
                  ctx.fillStyle = '#FFFFFF';
                  ctx.fill();
                }
        }
      })
      

      三、总结

      这个手写签名仅仅是为了业务应急使用。如果要优化的话,可以从笔锋模拟和笔迹模拟中入手。只不过要解决在实时模拟过程中卡顿的问题。

      jsjbwy
      下一篇:没有了