vue3 canvas實(shí)現(xiàn)手簽功能

記錄一下手簽功能代碼

<template>
  <div class="signName" :style="{ top: 0, left: differ + 'px'}">
    <div class="close" @click="close">X</div>
    <div class="autographBox">
      <div ref="canvasHW">
        <canvas @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" ref="canvasF" />
      </div>
      <p v-if="!isDraw">請(qǐng)本人簽名</p>
    </div>
    <div class="btn-box">
      <div @click="overwrite">重簽</div>
      <div @click="seaveImages">確定</div>
    </div>
  </div>
</template>
<script>
import { ref, onMounted } from 'vue'
export default {
  name: 'sign-canvas',
  setup(props, cxt) {
    let differ = ref(document.documentElement.clientWidth)
    let canvasF = ref(null)
    let canvasHW = ref(null)
    let canvasTxt = null // 畫布
    let points = [] // 記錄點(diǎn)
    let isDraw = ref(false) // 簽名標(biāo)記
    let startX = 0 // 開始坐標(biāo)x
    let startY = 0 // 開始坐標(biāo)y
    let moveY = 0
    let moveX = 0
    let strDataURI = '' // 保存的canvas圖像
    onMounted(() =>{
      let canvas = canvasF.value
      canvas.height = canvasHW.value.offsetHeight
      canvas.width = canvasHW.value.offsetWidth
      canvasTxt = canvas.getContext('2d')
      canvasTxt.strokeStyle = '#333'
      canvasTxt.lineWidth = '3'
    }) 
    const touchStart = (ev) => {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length == 1) {
        isDraw.value = true // 簽名標(biāo)記
        let obj = {
          x: ev.targetTouches[0].clientY,
          y: differ.value - ev.targetTouches[0].clientX - (differ.value * 0.08)
        } // y的計(jì)算值中:document.body.offsetHeight*0.5代表的是除了整個(gè)畫板signatureBox剩余的高盼忌,this.$refs.canvasHW.offsetHeight*0.1是畫板中標(biāo)題的高
        startX = obj.x
        startY = obj.y
        canvasTxt.beginPath() // 開始作畫
        points.push(obj) // 記錄點(diǎn)
      }
    }
    const touchMove = (ev)=> {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientY,
          y: differ.value- ev.targetTouches[0].clientX - (differ.value * 0.08)
        }
        moveY = obj.y
        moveX = obj.x
        canvasTxt.moveTo(startX, startY) // 移動(dòng)畫筆
        canvasTxt.lineTo(obj.x, obj.y) // 創(chuàng)建線條
        canvasTxt.stroke() // 畫線
        startY = obj.y
        startX = obj.x
        points.push(obj) // 記錄點(diǎn)
      }
    }
    const touchEnd = (ev)=> {
      ev = ev || event
      ev.preventDefault()
      if (ev.touches.length == 1) {
        let obj = {
          x: ev.targetTouches[0].clientY,
          y: differ.value- ev.targetTouches[0].clientX - (differ.value * 0.08)
        }
        points.push(obj) // 記錄點(diǎn)
        points.push({ x: -1, y: -1 }) // 記錄點(diǎn)
        canvasTxt.closePath() // 收筆
        canvasTxt.fill()
      }
    }
    const overwrite = ()=> {
      canvasTxt.clearRect(
        0,
        0,
        canvasF.value.width,
        canvasF.value.height
      )
      points = []
      isDraw.value = false // 簽名標(biāo)記
    }
    function seaveImages() {
      if (isDraw.value) {
        strDataURI = canvasF.value.toDataURL('image/png')
        cxt.emit('autographConfirm', {
          baseCode:strDataURI,
        })
      }
    }
    function close(){
      cxt.emit('close', {
        closeFlag:false,
      });
    }
    return {
      differ,
      canvasF,
      canvasHW,
      isDraw,
      touchStart,
      touchMove,
      touchEnd,
      overwrite,
      seaveImages,
      close
    }
  }
}
</script>
<style scoped lang="scss">
.signName {
  position: fixed;
  height: 100vw;
  width: 100vh;
  background-color: #fff;
  transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
  transform-origin: left top;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  p {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    font-size: 4rem;
    font-weight: bolder;
    color:#436CDF;
    opacity: 0.1;
  }
}
.btn-box {
  height: 12%;
  display: flex;
  align-items: center;
  padding-left: 2rem;
  div {
    width: 5rem;
    height: 60%;
    border: 1px solid #D10021;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #D10021;
    border-radius: .4rem;
  }
  div:last-child {
    margin-left: 2rem;
    background: linear-gradient(180deg, #D10021 0%, #AE000E 100%);
    color: #fff;
  }
}
.close {
  width: 100%;
  height: 8%;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: right;
  padding-right: 2rem;
}
.autographBox {
  flex: 1;
  background: rgba(227, 227, 227, 1);
  border-top: 4px solid rgba(212, 212, 212, 1);
  border-bottom: 4px solid rgba(212, 212, 212, 1);
  div {
    height: 100%;
  }
}
</style>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市兵罢,隨后出現(xiàn)的幾起案子渗饮,更是在濱河造成了極大的恐慌浩考,老刑警劉巖婶肩,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異说搅,居然都是意外死亡炸枣,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門弄唧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來适肠,“玉大人,你說我怎么就攤上這事候引∮睾铮” “怎么了?”我有些...
    開封第一講書人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵背伴,是天一觀的道長沸毁。 經(jīng)常有香客問我,道長傻寂,這世上最難降的妖魔是什么息尺? 我笑而不...
    開封第一講書人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮疾掰,結(jié)果婚禮上搂誉,老公的妹妹穿的比我還像新娘。我一直安慰自己静檬,他們只是感情好炭懊,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開白布并级。 她就那樣靜靜地躺著,像睡著了一般侮腹。 火紅的嫁衣襯著肌膚如雪嘲碧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評(píng)論 1 308
  • 那天父阻,我揣著相機(jī)與錄音愈涩,去河邊找鬼。 笑死加矛,一個(gè)胖子當(dāng)著我的面吹牛履婉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斟览,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼毁腿,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了苛茂?” 一聲冷哼從身側(cè)響起狸棍,我...
    開封第一講書人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎味悄,沒想到半個(gè)月后草戈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡侍瑟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年唐片,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涨颜。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡费韭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出庭瑰,到底是詐尸還是另有隱情星持,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布弹灭,位于F島的核電站督暂,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏穷吮。R本人自食惡果不足惜逻翁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捡鱼。 院中可真熱鬧八回,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至管引,卻和暖如春士败,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背汉匙。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留生蚁,地道東北人噩翠。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像邦投,于是被迫代替她去往敵國和親伤锚。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容