vue 签名

<template>
  <div ref="signaturePanel" class="signaturePanel">
    <div  class="title" ref="title"  @click="clearAll">请在下方区域签字</div>
    <canvas ref="drawingBoard" class="drawingBoard" @mousedown="mousedown" @mousemove="mousemove" @mouseup="mouseup" v-show="!mySignature"></canvas>
    <img class="drawingBoard" :src="mySignature" v-show="mySignature"/>
    <div class="clear" @click="clearAll"><img src="../img/clear.png"/>{{mySignature ? '重新签名':'清除'}}</div>
    <!-- <div class="nextBtn validate" @click="clearAll">提交</div> -->
    <!-- <input type="file" ref="textDom"/> -->
  </div>
</template>
<script>
import {uploadShareImages} from '../api/api'
export default {
  props: {
    signature: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      canvas: '',
      ctx: '',
      painting: false,
      lastPoint: {
        x: undefined,
        y: undefined
      },
      lineWidth: 2, // 画笔宽度
      color: '#000', // 画笔颜色
      mySignature: this.signature
      // width: 0, // 画布宽度
      // height: 0 // 画布高度
    }
  },
  watch: {
    signature(val) {
      this.mySignature = val
    }
  },
  mounted () {
    tuhu.store.commit('shopJoin/setPageIndex', 9)
    this.init()
    $(document).off('click', 'a') // 恢复a标签的默认事件
  },
  created() {
  },
  methods: {
    onPageBack() {
      // 监听页面返回
      tuhu.store.commit('shopJoin/setPageIndex', 9)
    },
    init () {
      this.ctx = this.$refs.drawingBoard.getContext('2d')
      this.$refs.drawingBoard.width = this.$refs.drawingBoard.offsetWidth
      this.$refs.drawingBoard.height = this.$refs.drawingBoard.offsetHeight
      this.ctx.strokeStyle = this.color
      // 在canvas绘制前填充白色背景,不然保存的png图片是透明的
      this.ctx.fillStyle = '#fff'
      this.ctx.fillRect(0, 0, this.$refs.drawingBoard.offsetWidth, this.$refs.drawingBoard.offsetHeight)

      const _this = this
      // 兼容移动端
      if (document.body && document.body.ontouchstart !== undefined) {
        _this.$refs.drawingBoard.ontouchstart = function (e) {
          _this.mousedown(e, 0)
          e.preventDefault()
        }
        _this.$refs.drawingBoard.ontouchmove = function (e) {
          _this.mousemove(e, 0)
        }
        _this.$refs.drawingBoard.ontouchend = function (e) {
          _this.mouseup(e, 0)
        }
      }
    },
    mousedown (e, flag = 1) {
      this.painting = true
      this.lastPoint = this.getPoint(e, flag)
    },
    mousemove (e, flag = 1) {
      if (!this.painting) {
        return
      }
      let newPoint = this.getPoint(e, flag)
      this.drawLine(this.lastPoint.x, this.lastPoint.y, newPoint.x, newPoint.y)
      this.lastPoint = newPoint
    },
    getPoint(e, flag = 1) {
      let x
      let y
      try {
        let clientY = flag ? e.clientY : e.touches[0].clientY
        x = flag ? e.offsetX : e.touches[0].clientX
        y = clientY - this.$refs.title.offsetHeight - this.$refs.signaturePanel.offsetTop + this.$refs.signaturePanel.offsetParent.scrollTop
      } catch (error) {
        tuhu.alert(error)
      }

      return {x: x, y: y}
    },
    mouseup () {
      this.painting = false
    },
    drawLine (x1, y1, x2, y2) {
      this.ctx.lineWidth = this.lineWidth
      this.ctx.lineCap = 'round'
      this.ctx.lineJoin = 'round'
      this.ctx.moveTo(x1, y1)
      this.ctx.lineTo(x2, y2)
      this.ctx.stroke()
      this.ctx.closePath()
    },
    clearAll () {
      if (this.mySignature) {
        this.mySignature = ''
        this.$nextTick(() => {
          this.init()
        })
      } else {
          // this.ctx.height = this.$refs.drawingBoard.offsetHeight
        this.ctx.clearRect(0, 0, this.$refs.drawingBoard.offsetWidth, this.$refs.drawingBoard.offsetHeight)
        this.ctx.beginPath()   // 开启新路径,防止连笔
          // 清除以后要重新绘制背景图
        this.ctx.fillStyle = '#fff'
        this.ctx.fillRect(0, 0, this.$refs.drawingBoard.offsetWidth, this.$refs.drawingBoard.offsetHeight)
      }
    },
    convertBase64UrlToBlob(urlData) {
      let bytes = window.atob(urlData.split(',')[1])        // 去掉url的头,并转换为byte
        // 处理异常,将ascii码小于0的转换为大于0
      let ab = new ArrayBuffer(bytes.length)
      let ia = new Uint8Array(ab)
      for (let i = 0; i < bytes.length; i++) {
        ia[i] = bytes.charCodeAt(i)
      }
      return new Blob([ab], {type: 'image/png'})
    },
    save () { // 当前项目阻止了a标签的默认事件
      if (this.mySignature) {
        return this.mySignature
      }
      let imgUrl = ''
      try {
        imgUrl = this.$refs.drawingBoard.toDataURL('image/png')
      } catch (error) {
        tuhu.alert(error)
        tuhu.alert('请清除签名后,重新签名')
      }
      let formData = new FormData()
      // console.log(this.$refs.textDom.files[0])
      // formData.append('img', this.$refs.textDom.files[0])
      formData.append('imageName', this.convertBase64UrlToBlob(imgUrl))
      return uploadShareImages(formData)
        .then((res) => {
          tuhu.hidePreloader()
          return res && res.filename
        }).catch((e) => {
          tuhu.hidePreloader()
          tuhu.toast('签名上传失败,请重新上传')
          return ''
        })
    }
  }
}
</script>
<style lang="less" scoped>
  .signaturePanel {
    // overflow: hidden;
    font-size: 14px;
    background: #fff;
    padding-bottom: 2.25rem;
    position: relative;
    &::after{
      width: 100%;
      content: '签字区';
      position: absolute;
      top: 50% - 1rem;
      left: 0;
      font-size: 3rem;
      text-align: center;
      transform: translateY(-50%);
      color: #F5F5F5;
      z-index: -1;
    }
    .title{
      height: 2rem;
      padding: .6rem 0 .3rem .75rem;
      color: #999;
      font-weight: 400;
    }
    .drawingBoard {
      width: 100%;
      height: 12rem;
      border: 1px solid #eee;
    }
    .clear {
      height: 1.4rem;
      line-height: 1.4rem;
      color: #666;
      background: #F5F5F5;
      border-radius: .7rem;
      padding: 0 .5rem;
      position: absolute;
      bottom: .7rem;
      right: .7rem;
      z-index: 99;
      text-align: center;
      vertical-align: top;
      img{
        width: .7rem;
        height: .7rem;
        margin-right: .1rem;
        transform: translateY(.1rem)
      }
    }
    // .save {
    //   background-color: #f00;
    //   position: absolute;
    //   top: 0;
    //   right: 0;
    //   z-index: 1;
    // }
  }
</style>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343