uniapp小程序实现横屏手写签名(整理)

简介: uniapp小程序实现横屏手写签名(整理)

效果图:

方案一作为参考:

<template>
  <view class="signBox">
    <view class="topHint">请在下方空白书写区域内写出您的名字</view>
    <view class="btn">
      <view class="saveBtn" @click="save">确认</view>
      <view class="cancelBtn" @click="clear">清除</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>
  export default {
    components: {},
    data() {
      return {
        dom: null,
        line: [],
        radius: 0,
        width: '0rpx',
        height: '0rpx',
      }
    },
    onLoad() {},
    computed: {},
    created() {
      uni.getSystemInfo({
        success: (res) => {
          this.width = res.windowWidth - 60 + 'rpx';
          this.height = res.windowHeight - 56 + 'rpx';
        }
      });
      this.dom = uni.createCanvasContext('designature', this);
    },
    onShow() {},
    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) {
        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) {
        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.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) {
            t.$emit('getImg', res.tempFilePath)
            console.log(res.tempFilePath, '148')
            // uni.navigateBack({
            //     delta:1
            // })
          },
          fail(e) {
            console.log(e)
          }
        }, this)
      }
    }
  }
</script>
<style scoped lang="less">
  .signBox {
    position: relative;
    overflow: hidden;
    background-color: #F6F6F6;
    height: 100vh;
    width: 100vw;
    .canvas {
      width: 100% !important;
      background-color: #FFFFFF;
      position: absolute;
      z-index: 9999;
      left: 0rpx;
      top: 25rpx;
      // border: 1rpx solid #d6d6d6;
    }
    .topHint{
      width: 100%;
      height: 25rpx;
      line-height: 25rpx;
      font-size: 15rpx;
      color: #999999;
      text-align: center;
      background: ;
    }
    .btn {
      width: 100%;
      height: 60rpx;
      position: fixed;
      bottom: 0;
      // background-color: red;
      display: flex;
      align-items: center;
      justify-content: center;
      .saveBtn {
        width: 190rpx;
        height: 40rpx;
        line-height: 40rpx;
        background: linear-gradient(306deg, #4281EA 0%, #6363F2 100%);
        border-radius: 10rpx;
        text-align: center;
        font-size: 18rpx;
        color: #FFFFFF;
        margin-right: 10rpx;
      }
      .cancelBtn {
        width: 190rpx;
        height: 40rpx;
        line-height: 40rpx;
        background: #FFFFFF;
        border-radius: 10rpx;
        text-align: center;
        font-size: 18rpx;
        color: #222222;
        margin-left: 10rpx;
      }
    }
  }
</style>
json文件
{
  "path": "pages/clientDitch/sign",
  "style": {
    "navigationBarTitleText": "签字手签",
    "pageOrientation": "landscape", //控制横屏
    // "navigationStyle": "custom"
  }
}, 

方案二是demo-用这个:

<template>
  <view class="signBox column-me">
    <!-- 这个是自定义的title-可根据自己封装的title的作为调整 -->
    <status-bar title="电子签名" :bgColor="null"></status-bar>
    <view class="topHint">请绘制清晰可辨的签名并保存</view>
    <canvas class="canvas flex1" :canvas-id="cid" :id="cid" @touchstart="touchstart" @touchmove="touchmove"
      @touchend="touchend" :disable-scroll="true"></canvas>
    <view class="btn margin-top10 margin-bottom10">
      <view class="cancelBtn" @click="reWrite">重写</view>
      <view class="saveBtn margin-left30" @click="save">保存</view>
    </view>
  </view>
</template>
<script>
  export default {
    components: {},
    data() {
      return {
        line: [],
        radius: 0,
        taskId: '',
        //以下与签名有关参数
        dom: null,
        cid: 'canvas', //画布id
        Strokes: [],
        showCanvasDialog: false,
        canvasImg: '', //签名图片
      }
    },
    onLoad(e) {
      this.taskId = e.taskId
    },
    computed: {},
    mounted: function() {
      let that = this
      this.initCanvas()
    },
    methods: {
      initCanvas() {
        let that = this
        this.$nextTick(function() {
          this.dom = uni.createCanvasContext(this.cid, this);
          var query = wx.createSelectorQuery();
          query.select('#canvas').boundingClientRect();
          query.exec(function(res) {
            let widths = res[0].width
            let heights = res[0].height
            that.dom.rect(0, 0, widths, heights)
            that.dom.setFillStyle('#FFFFFF')
            that.dom.fill()
            that.dom.draw()
          })
        });
      },
      touchstart(e) {
        this.Strokes.push({
          imageData: null,
          style: {
            color: '#000000',
            lineWidth: '3',
          },
          points: [{
            x: e.touches[0].x,
            y: e.touches[0].y,
            type: e.type,
          }]
        })
        this.drawLine(this.Strokes[this.Strokes.length - 1], e.type);
      },
      touchmove(e) {
        this.Strokes[this.Strokes.length - 1].points.push({
          x: e.touches[0].x,
          y: e.touches[0].y,
          type: e.type,
        })
        this.drawLine(this.Strokes[this.Strokes.length - 1], e.type);
      },
      touchend(e) {
        if (this.Strokes[this.Strokes.length - 1].points.length < 2) { //当此路径只有一个点的时候
          this.Strokes.pop();
        }
      },
      drawLine(StrokesItem, type) {
        if (StrokesItem.points.length > 1) {
          this.dom.setLineCap('round')
          this.dom.setStrokeStyle(StrokesItem.style.color);
          this.dom.setLineWidth(StrokesItem.style.lineWidth);
          this.dom.moveTo(StrokesItem.points[StrokesItem.points.length - 2].x, StrokesItem.points[StrokesItem
            .points.length -
            2].y);
          this.dom.lineTo(StrokesItem.points[StrokesItem.points.length - 1].x, StrokesItem.points[StrokesItem
            .points.length -
            1].y);
          this.dom.stroke();
          this.dom.draw(true);
        }
      },
      //重写签名
      reWrite() {
        this.Strokes = [];
        this.dom.draw();
        this.initCanvas()
      },
      // 保存图片
      save() {
        let that = this
        uni.canvasToTempFilePath({
          canvasId: 'canvas',
          fileType: 'png',
          quality: 1, //图片质量
          success: function(res) {
            let imgs = [res.tempFilePath]
            that.$.upload_img(imgs, 0, res => {
              let imgUrl = res.data //签名图片
              let mediaUrl = that.$.get_data('mediaUrl') //采集图片
              if (that.$.isEmpty(mediaUrl)) {
                mediaUrl = ''
              }
              that.$.ajax("POST", "/customer/user/checkTask", {
                taskId: that.taskId,
                status: 1, //状态:1同意2拒绝  
                signImage: imgUrl,
                userVideo: mediaUrl,
              }, (res) => {
                if (res.code === 1000) {
                  that.$.ti_shi(res.message)
                  setTimeout(() => {
                    uni.$emit('signOk')
                    that.$.back()
                  }, 1000)
                } else {
                  that.$.ti_shi(res.message)
                }
              });
            })
          },
          fail(e) {
            console.log(e)
          }
        })
      }
    }
  }
</script>
<style scoped lang="less">
  .signBox {
    position: relative;
    overflow: hidden;
    background-color: #F6F6F6;
    height: 100vh;
    width: 100vw;
    .canvas {
      width: 100%;
      background: #FFFFFF;
    }
    .topHint {
      width: 100%;
      height: 60rpx;
      line-height: 60rpx;
      font-size: 28rpx;
      color: #6D7984;
      text-align: center;
      background: ;
    }
    .btn {
      width: 100%;
      height: 132rpx;
      display: flex;
      align-items: center;
      justify-content: center;
      .saveBtn {
        width: 300rpx;
        height: 88rpx;
        line-height: 88rpx;
        background: #215AA0;
        border-radius: 20rpx;
        text-align: center;
        font-size: 32rpx;
        color: #FFFFFF;
      }
      .cancelBtn {
        width: 298rpx;
        height: 86rpx;
        line-height: 86rpx;
        background: #FFFFFF;
        border-radius: 20rpx;
        text-align: center;
        font-size: 32rpx;
        color: #202233;
        border: 1px solid #BBC4CC;
      }
    }
  }
</style>
相关文章
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的QQ村旅游网站附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的QQ村旅游网站附带文章和源代码设计说明文档ppt
14 5
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的大湾区旅游推荐系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的大湾区旅游推荐系统附带文章和源代码设计说明文档ppt
17 4
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的物流配送管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的物流配送管理系统附带文章和源代码设计说明文档ppt
10 2
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的电影购票系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的电影购票系统附带文章和源代码设计说明文档ppt
9 3
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的健身房会员管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的健身房会员管理系统附带文章和源代码设计说明文档ppt
10 3
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的车辆出租管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的车辆出租管理系统附带文章和源代码设计说明文档ppt
11 3
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的疫情防控管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的疫情防控管理系统附带文章和源代码设计说明文档ppt
6 1
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的校园二手交易平台的设计与开发附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的校园二手交易平台的设计与开发附带文章和源代码设计说明文档ppt
13 2
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的博客系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的博客系统附带文章和源代码设计说明文档ppt
9 2
|
2天前
|
JavaScript Java 测试技术
基于ssm+vue.js+uniapp小程序的教材管理系统附带文章和源代码设计说明文档ppt
基于ssm+vue.js+uniapp小程序的教材管理系统附带文章和源代码设计说明文档ppt
8 1