您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“vue3.0怎么實(shí)現(xiàn)移動(dòng)端電子簽名組件”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“vue3.0怎么實(shí)現(xiàn)移動(dòng)端電子簽名組件”吧!
因業(yè)務(wù)需求,前段時(shí)間寫了一個(gè)電子簽名組件,在這里記錄一下,繪圖需求,首先肯定需要使用
canvas標(biāo)簽,考慮到在移動(dòng)端使用,所以選擇使用touch事件。
首先奉上html結(jié)構(gòu)(該組件為橫屏展示):
<div class="signName" :> <div class="close" @click="close"><img src="../assets/images/close.png" alt=""></div> <div class="autographBox"> <div ref="canvasHW"> <canvas @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" ref="canvasF" ></canvas> </div> <p v-if="!isDraw">請(qǐng)本人簽名</p> </div> <div class="autographBtn"> <div @click="overwrite">重簽</div> <div @click="seaveImages">確定</div> </div> </div>
css樣式:
.signName{ position: fixed; height: 100vw; width: 100vh; background-color: #fff; transform:rotate(90deg); -webkit-transform:rotate(90deg); transform-origin: left top; z-index: 1000; /* top:0; left: 0; */ } .close{ width: 100%; height: 10%; padding-left: 2.5rem; padding-top: 1.2rem; } .close img{ width: 2rem; } .autographBox{ width: 100%; height: 80%; position: relative; } .autographBox div{ width: 100%; height: 100%; } .autographBox canvas{ width: 100%; height: 100%; } .signName p{ position: absolute; top:50%; left: 50%; transform: translate(-50%,-50%); font-size: 4rem; font-weight: bolder; color:#436CDF; opacity: 0.1; } .autographBtn{ width: 100%; height: 10%; display: flex; justify-content: center; align-items: center; } .autographBtn div{ width: 50%; height: 100%; color: #fff; display: flex; justify-content: center; align-items: center; font-size: 1.3rem; } .autographBtn div:first-child{ opacity: 0.4; background: -webkit-linear-gradient(top, #728CFD 0%,#5C7EFE 100%); } .autographBtn div:last-child{ background: -webkit-linear-gradient(top, #728CFD 0%,#5C7EFE 100%); }
其次定義變量,初始化canvas:
var differ = ref(document.documentElement.clientWidth) var canvasF = ref(null); var canvasHW = ref(null); var canvasTxt = null; //畫布 var points = []; // 記錄點(diǎn) var isDraw = ref(false); //簽名標(biāo)記 var startX = 0; //開始坐標(biāo)x var startY = 0;//開始坐標(biāo)y var moveY= 0; var moveX= 0; var strDataURI ='' // 保存的canvas圖像 onMounted(() =>{ let canvas =canvasF.value; canvas.height = canvasHW.value.offsetHeight - 10; canvas.width = canvasHW.value.offsetWidth - 10; canvasTxt = canvas.getContext("2d"); canvasTxt.strokeStyle = '#333'; canvasTxt.lineWidth = '3'; })
主要事件方法如下:
1、touchstart
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.1) }; //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) } }
2、touchmove
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.1) }; 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) } }
3、touchend
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.1) }; points.push(obj);//記錄點(diǎn) points.push({ x: -1, y: -1 });//記錄點(diǎn) canvasTxt.closePath();//收筆 canvasTxt.fill(); } }
4、重寫
const overwrite = ()=> { canvasTxt.clearRect( 0, 0, canvasF.value.width, canvasF.value.height ); points = []; isDraw.value = false; //簽名標(biāo)記 }
5、保存圖片
function seaveImages() { if(isDraw.value){ strDataURI = canvasF.value.toDataURL("image/png"); console.log(strDataURI) cxt.emit("autographConfirm", { baseCode:strDataURI, }); }else{ console.log(Toast); Toast('您還沒有簽名') } }
最后附上完整代碼:
<template> <div class="signName" :> <div class="close" @click="close"><img src="../assets/images/close.png" alt=""></div> <div class="autographBox"> <div ref="canvasHW"> <canvas @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" ref="canvasF" ></canvas> </div> <p v-if="!isDraw">請(qǐng)本人簽名</p> </div> <div class="autographBtn"> <div @click="overwrite">重簽</div> <div @click="seaveImages">確定</div> </div> </div> </template> <script> import { ref, onMounted } from "vue"; import { Toast } from "vant"; export default { name: "index", setup(props,cxt) { var differ = ref(document.documentElement.clientWidth) var canvasF = ref(null); var canvasHW = ref(null); var canvasTxt = null; //畫布 var points = []; // 記錄點(diǎn) var isDraw = ref(false); //簽名標(biāo)記 var startX = 0; //開始坐標(biāo)x var startY = 0;//開始坐標(biāo)y var moveY= 0; var moveX= 0; var strDataURI ='' // 保存的canvas圖像 onMounted(() =>{ let canvas =canvasF.value; canvas.height = canvasHW.value.offsetHeight - 10; canvas.width = canvasHW.value.offsetWidth - 10; 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.1) }; //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.1) }; 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.1) }; 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"); console.log(strDataURI) cxt.emit("autographConfirm", { baseCode:strDataURI, }); }else{ console.log(Toast); Toast('您還沒有簽名') } } function close(){ cxt.emit("close", { closeFlag:false, }); } return { differ, canvasF, canvasHW, isDraw, touchStart, touchMove, touchEnd, overwrite, seaveImages, close }; }, }; </script> <style scoped> .signName{ position: fixed; height: 100vw; width: 100vh; background-color: #fff; transform:rotate(90deg); -webkit-transform:rotate(90deg); transform-origin: left top; z-index: 1000; /* top:0; left: 0; */ } .close{ width: 100%; height: 10%; padding-left: 2.5rem; padding-top: 1.2rem; } .close img{ width: 2rem; } .autographBox{ width: 100%; height: 80%; position: relative; } .autographBox div{ width: 100%; height: 100%; } .autographBox canvas{ width: 100%; height: 100%; } .signName p{ position: absolute; top:50%; left: 50%; transform: translate(-50%,-50%); font-size: 4rem; font-weight: bolder; color:#436CDF; opacity: 0.1; } .autographBtn{ width: 100%; height: 10%; display: flex; justify-content: center; align-items: center; } .autographBtn div{ width: 50%; height: 100%; color: #fff; display: flex; justify-content: center; align-items: center; font-size: 1.3rem; } .autographBtn div:first-child{ opacity: 0.4; background: -webkit-linear-gradient(top, #728CFD 0%,#5C7EFE 100%); } .autographBtn div:last-child{ background: -webkit-linear-gradient(top, #728CFD 0%,#5C7EFE 100%); } </style>
到此,相信大家對(duì)“vue3.0怎么實(shí)現(xiàn)移動(dòng)端電子簽名組件”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。