移动端下,旋转屏幕手写签名, 本身canvas签名不难,不想费事直接用SignaturePad插件了,主要记录移动端踩坑

实现方式

<template>
  <div class='recruit-canvas'>
    <canvas id="canvas-map" width="100%" height="100%"></canvas>
    <div class="btn-box flex-row">
      <span class="del-btn" @click="clearCanvasHandle">清除</span>
      <span class="sure-btn" @click="makeCanvasHandle">确认</span>
    </div>
  </div>
</template>

<script>
import SignaturePad from 'signature_pad'
export default {
  name: 'MineRecruitCanvas',
  data () {
    return {
      canvasNode: null
    }
  },
  mounted () {
    this.initialCanvasChange()
    window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', this.onWatchOrientation, false)
  },
  methods: {
    onWatchOrientation () {
      window.location.reload()
    },

    initialCanvasChange () {
      const _canvas = document.getElementById('canvas-map')
      const _width = window.innerWidth
      const _height = window.innerHeight
      // 正常方向或屏幕旋转180度, 竖屏状态
      if (window.orientation === 180 || window.orientation === 0) {
        alert('竖屏状态' + 'width: ' + _width + 'height: ' + _height)

        _canvas.width = _width
        _canvas.height = _height
      }

      // 屏幕顺时钟旋转90度或屏幕逆时针旋转90度, 横屏状态
      if (window.orientation === 90 || window.orientation === -90) {
        alert('横屏状态' + 'width: ' + _width + 'height: ' + _height)

        _canvas.width = _width
        _canvas.height = _height
      }

      this.canvasNode = new SignaturePad(_canvas, {
        minWidth: 1,
        maxWidth: 2,
        penColor: 'rgb(66, 133, 244)'
      })
      this.clearCanvasHandle()
    },

    clearCanvasHandle () {
      if (this.canvasNode) {
        this.canvasNode.clear()
      }
    },

    makeCanvasHandle () {
      const path = this.canvasNode.toDataURL('image/png', 0.6)
      if (path) {
        console.log(path)
        // do something here
      } else {
        alert('保存失败,请重新签名')
        this.clearCanvasHandle()
      }
    }
  },
  beforeDestroy () {
    window.removeEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', this.onWatchOrientation)
  }
}
</script>

<style lang='scss' scoped>
.recruit-canvas {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;

  .btn-box{
    position: absolute;
    bottom: 20px;
    left: 0;
    width: 100%;
    z-index: 200;
    text-align: center;
    padding: 0 40px;
    margin-top: 20px;
    box-sizing: border-box;

    .del-btn,
    .sure-btn {
      display: inline-block;
      flex: 1;
      height: 40px;
      margin: 0 10px;
      line-height: 40px;
      border-radius: 6px;
      background-color: $color-background;
    }

    .del-btn {
      color: $color-theme;
    }

    .sure-btn {
      color: $color-background;
      background: linear-gradient(100deg, #FF4E01 0%, #FFBC01 100%);
    }
  }

  #canvas-map {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 150;
  }
}
</style>

踩坑记录

1 . 移动端屏幕旋转,canvas触控点失灵,签名位置错乱

解决方案不唯一,

首先canvas的父容器(class='recruit-canvas')固定定位在body下,默认宽高继承body,100%;

其次,定位canvas采用定位,脱离文档流,动态设定宽高即可(宽高设置无效看踩坑三)

2 . 安卓微信下,网页无法旋转,IOS下网页旋转正常

ios手机权限高于微信,所以微信**旋转方向**默认开启跟随系统

android手机下,微信默认关闭旋转跟随系统,打开设置步骤:我的-设置-通用-开启横屏模式(跟随系统旋转)

3 . canvas赋值宽高无效

canvas.style.width/height 与 canvas.width/height 设置不同,

单独设置canvas.width/height前提需要在html标签中初始化默认width,height属性;
单独设置canvas.style.width/height,需要在后面添加'px'单位,否则失效;

备注:实际测试中Google chrome,发现不设置属性依然可以设置canvas.width/height,可能与兼容性有关