index.vue 7.2 KB
<template>
  <view class="signa">
    <view class="title">
      请横屏进行手绘签名
    </view>
    <view class="btn">
      <view class="cancel-btn" @click="clear">
        清除
      </view>
      <view class="save-btn" @click="save">
        确定
      </view>
    </view>
    <canvas class="canvas" disable-scroll="true" :style="{'width':width,'height':height}" canvas-id="designature"
      @touchstart="starts" @touchmove="moves" @touchend="end"></canvas>
  </view>
</template>

<script>
  /*
   *	已兼容h5和小程序端
   * 
   *	如有问题可以加qq:122720267
   * 	里面的计算都是自己转换公式得出的,不容易啊
   *	使用该插件的朋友请给个好评,或者到git start一下
   * 
   */
  export default {
    data() {
      return {
        resultUrl: '',
        dom: null,
        line: [],
        width: '0px',
        height: '0px',
        radius: 0,
        tempFilePath: ''
      }
    },
    created() {
      uni.getSystemInfo({
        success: (res) => {
          this.width = res.windowWidth - 80 + 'px';
          this.height = res.windowHeight - 120 + 'px';
        }
      });
      this.dom = uni.createCanvasContext('designature', this);

    },
    methods: {
      end(e) {

      },
      distance(a, b) {
        let x = b.x - a.x;
        let y = b.y - a.y;
        return Math.sqrt(x * x + y * y);
      },
      starts(e) {
        console.log(e)
        this.line.push({
          points: [{
            time: new Date().getTime(),
            x: e.touches[0].x,
            y: e.touches[0].y,
            dis: 0
          }]
        })
        let currentPoint = {
          x: e.touches[0].x,
          y: e.touches[0].y
        }
        this.currentPoint = currentPoint
        this.drawer(this.line[this.line.length - 1])
      },
      moves(e) {
        console.log(e)
        let point = {
          x: e.touches[0].x,
          y: e.touches[0].y
        }
        this.lastPoint = this.currentPoint,
          this.currentPoint = point
        this.line[this.line.length - 1].points.push({
          time: new Date().getTime(),
          x: e.touches[0].x,
          y: e.touches[0].y,
          dis: this.distance(this.currentPoint, this.lastPoint)
        })
        this.drawer(this.line[this.line.length - 1])
      },
      drawer(item) {
        let x1, x2, y1, y2, len, radius, r, cx, cy, t = 0.5,
          x, y;
        var time = 0;
        if (item.points.length > 2) {
          let lines = item.points[item.points.length - 3];
          let line = item.points[item.points.length - 2];
          let end = item.points[item.points.length - 1];
          x = line.x;
          y = line.y;
          x1 = lines.x;
          y1 = lines.y;
          x2 = end.x;
          y2 = end.y;
          var dis = 0;
          time = (line.time - lines.time) + (end.time - line.time)
          dis = line.dis + lines.dis + end.dis;
          var dom = this.dom;
          var or = Math.min(time / dis * this.linePressure + this.lineMin, this.lineMax);
          cx = (x - (Math.pow(1 - t, 2) * x1) - Math.pow(t, 2) * x2) / (2 * t * (1 - t))
          cy = (y - (Math.pow(1 - t, 2) * y1) - Math.pow(t, 2) * y2) / (2 * t * (1 - t))
          dom.setLineCap('round')
          dom.beginPath();
          dom.setStrokeStyle('black')
          // dom.setFillStyle('white')
          // dom.fillRect(0, 0, 600, 600)
          // dom.fillStyle = '#fff';
          // dom.fillRect(0, 0, this.width, this.height);
          dom.setLineWidth(5)
          dom.moveTo(x1, y1);
          dom.quadraticCurveTo(cx, cy, x2, y2);
          dom.stroke();
          dom.draw(true)
        }

      },
      clear() {
        this.dom.clearRect(0, 0, 1000, 1000)
        this.dom.draw()
      },
      save() {
        var t = this;
        uni.canvasToTempFilePath({
          canvasId: 'designature',
          fileType: 'png',
          quality: 1, //图片质量
          success: function(res) {
            console.log(res.tempFilePath, '-----------------')
            // const tempFilePaths = res.tempFilePath;
            t.tempFilePath = res.tempFilePath
            uni.saveImageToPhotosAlbum({
              filePath: res.tempFilePath,
              success: function() {
                uni.showToast({
                  title: '保存成功'
                })
                console.log('save success');
              },
              fail(err) {
                // console.log('拒绝授权相册===========', err);
                if (err.errMsg == 'saveImageToPhotosAlbum:fail auth deny') {
                  // console.log('+++++++++++++++++++++++++');
                  uni.showModal({
                    content: '检测到您没打开此小程序的相机权限,是否去设置打开?',
                    confirmText: "确认",
                    cancelText: "取消",
                    success: function(res) {
                      // console.log(res, '==================');
                      //点击“确认”时打开设置页面
                      if (res.confirm) {
                        // console.log('用户点击确认')
                        uni.openSetting({
                          success: (res) => {
                            if (res.authSetting['scope.writePhotosAlbum']) {
                              // console.log('用户已开启权限');
                            }
                          }
                        })
                      } else {
                        console.log('用户点击取消')
                      }
                    }
                  });

                }
              }

            });
            t.$emit('getImg', res.tempFilePath)
          },
          fail(e) {

            console.log(e, '-------------')
          }
        }, this)
      }
    }
  }
</script>

<style scoped lang="scss">
  .signa {
    position: relative;
    overflow: hidden;
    background-color: #fbfbfb;
    height: 100vh;
    width: 100vw;

    .title {
      margin-top: 40rpx;
      margin-bottom: 132rpx;
      display: flex;
      justify-content: center;
      align-items: center;
      color: rgba(188, 192, 204, 1);
      font-size: 32rpx;
    }

    .canvas {
      background-color: #FFFFFF;
      position: absolute;
      z-index: 9999;
      left: 60px;
      // border: 1px solid #d6d6d6;
    }

    .btn {
      height: 50vh;
      position: fixed;
      background-color: #007AFF;
      font-size: 32rpx;

      .cancel-btn {
        width: 44vw;
        position: fixed;
        left: 50rpx;
        transform: rotate(90deg);
        color: #666;
        color: #000;
        margin-left: -21vw;
        margin-top: 40vh;
        height: 88rpx;
        line-height: 88rpx;
        border-radius: 16rpx;
        text-align: center;
        justify-content: center;
        background: #f1f5fb;
      }

      .save-btn {
        position: absolute;
        z-index: 999;
        display: inline-flex;
        margin-top: 67vh;
        margin-left: -21vw;
        transform: rotate(90deg);
        width: 44vw;
        background-color: #f22f21;
        left: 50rpx;
        border-radius: 16rpx;
        color: #fff;
        height: 88rpx;
        line-height: 88rpx;
        text-align: center;
        justify-content: center;
      }
    }
  }
</style>