vue+canvas實(shí)現(xiàn)移動(dòng)端手寫簽名
本文實(shí)例為大家分享了vue+canvas實(shí)現(xiàn)移動(dòng)端手寫簽名的具體代碼,供大家參考,具體內(nèi)容如下
<template>
<div class="sign">
<div class="header">
<i class="el-icon-arrow-left backImg" @click="goBack"></i>
<span class="title">個(gè)人簽名</span>
</div>
<section class="signature">
<div class="signatureBox">
<div class="canvasBox" ref="canvasHW">
<canvas ref="canvasF" class="canvasStyle" @touchstart='touchStart' @touchmove='touchMove' @touchend='touchEnd' @mousedown="mouseDown" @mousemove="mouseMove" @mouseup="mouseUp"></canvas>
</div>
</div>
</section>
<div class="btnBox">
<div @click="overwrite" class="btn1">重置</div>
<div @click="commit" class="btn1">確定</div>
</div>
<div class="imglist-box" :style="imgUrlList.length>0 ? 'border: 1px solid #d9d9d9;' : ''">
<img v-for="i in imgUrlList" class="imgCanvas" :src="i">
<img v-show="imgUrlList.length>0" src="../../assets/img/signdelete.png" class="resign" @click="deleteAll">
</div>
<div class="tijiao-box">
<button @click="commitAll" class="tijiao">提 交</button>
</div>
</div>
</template>
<script>
import { Bus } from '@/utils'
export default {
name:'personsign',
data() {
return {
stageInfo:'',
imgUrl:'',
imgUrlList:[],
client: {},
points: [],
canvasTxt: null,
startX: 0,
startY: 0,
moveY: 0,
moveX: 0,
endY: 0,
endX: 0,
w: null,
h: null,
isDown: false,
isViewAutograph: this.$route.query.isViews > 0,
contractSuccess: this.$route.query.contractSuccess,
}
},
mounted() {
let canvas = this.$refs.canvasF
canvas.height = this.$refs.canvasHW.offsetHeight -0
canvas.width = this.$refs.canvasHW.offsetWidth - 0
this.canvasTxt = canvas.getContext('2d')
this.canvasTxt.lineWidth = 4
this.stageInfo = canvas.getBoundingClientRect()
},
methods: {
goBack(){
this.$router.go(-1)
// session.clear()
},
//mobile
touchStart(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clienX,
y: ev.targetTouches[0].clientY,
}
this.startX = obj.x
this.startY = obj.y
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
}
},
touchMove(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX - this.stageInfo.left,
y: ev.targetTouches[0].clientY - this.stageInfo.top
}
this.moveY = obj.y
this.moveX = obj.x
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.startY = obj.y
this.startX = obj.x
this.points.push(obj)
}
},
touchEnd(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX - this.stageInfo.left,
y: ev.targetTouches[0].clientY - this.stageInfo.top
}
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
}
},
//pc
mouseDown(ev) {
ev = ev || event
ev.preventDefault()
if (1) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.startX = obj.x
this.startY = obj.y
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
// this.canvasTxt.strokeRect(20,20,80,100);
this.canvasTxt.closePath()
this.points.push(obj)
this.isDown = true
}
},
mouseMove(ev) {
ev = ev || event
ev.preventDefault()
if (this.isDown) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.moveY = obj.y
this.moveX = obj.x
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.startY = obj.y
this.startX = obj.x
this.points.push(obj)
}
},
mouseUp(ev) {
ev = ev || event
ev.preventDefault()
if (1) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
this.points.push({x: -1, y: -1})
this.isDown = false
}
},
//重寫
overwrite() {
this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
this.points = []
},
//確定簽名
commit() {
this.imgUrl=this.$refs.canvasF.toDataURL();
this.imgUrlList.push(this.imgUrl)
if(this.imgUrlList.length>0){
this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
this.points = []
}
},
deleteAll(){
this.imgUrlList = []
},
// 提交簽名給前一頁
commitAll(){
// 用canvas合并多張圖片的base64為一張圖的base64
var canvas = document.createElement("canvas");
canvas.width = 75*this.imgUrlList.length;
canvas.height = 100;
var context = canvas.getContext("2d");
context.rect(0 , 0 , canvas.width , canvas.height);
context.fillStyle = "#fff";
context.fill();
var myImage = new Image();
myImage.crossOrigin = 'Anonymous';
// 當(dāng)簽名列表有值時(shí)
if(this.imgUrlList.length>0){
for(let i = 0;i<this.imgUrlList.length;i++){
myImage.src = this.imgUrlList[i]
// 多張圖片繪制成一張圖片
context.drawImage(myImage , 50*i , 0 , 75 , 75); //context.drawImage(img,x,y,width,height);
// context.font = "60px Courier New";
// context.fillText("我是文字",350,450);
}
var base64 = canvas.toDataURL("image/jpg"); //"image/jpg" 這里注意一下
this.$router.go(-1) //要在bus之前寫不然值傳不回去
setTimeout(() => {
Bus.$emit('signImage',base64) //簽名base64傳給前一頁
}, 300)
}
}
},
beforeDestroy(){
// 銷毀bus
Bus.$off()
}
}
</script>
<style scoped lang="scss">
// 簽名樣式很重要,會(huì)影響觸點(diǎn)位置
.sign{
width: 100%;
min-height: 100vh;
position: relative;
.header{
margin-bottom: 20px;
}
.tijiao-box{
width: 100%;
text-align: center;
}
.tijiao{
width: 90%;
height: 84px;
color: #fff;
border-radius: 2px;
background: #fa4b31;
box-shadow: 0 0 0px 1px #fa4b31;
font-size: 30px;
}
}
.signature{
width: 100%;
height: 50vh;
}
.imglist-box{
width: 90%;
margin: 0 auto;
margin-bottom: 20px;
position: relative;
}
.imgCanvas{
width: 150px;
height: 150px;
}
.resign{
width: 14%;
position: absolute;
top: 0;
right: 0;
}
.signatureBox {
width: 90%;
margin: 0 auto;
height: calc(100% - 50px);
box-sizing: border-box;
overflow: hidden;
background: #fff;
z-index: 100;
display: flex;
flex-direction: column;
align-items: center;
}
.canvasBox {
width: 100%;
align-items: center;
box-sizing: border-box;
flex: 1;
}
canvas {
background-image: url('../../assets/img/signbg.png');
background-position: center center;
background-repeat: no-repeat;
background-origin: border-box;
background-size: 100% 100%;
}
.btnBox{
width: 90%;
margin: 0 auto;
display: flex;
justify-content: space-between;
margin-bottom: 20px;
.btn1{
width: 46%;
height: 84px;
line-height: 84px;
color: #fa4b31;
border-radius: 2px;
background: #fff;
border: 1px solid #fa4b31;
box-shadow: 0 0 0px 1px #fa4b31;
font-size: 30px;
text-align: center;
}
}
.btnBox button:first-of-type {
background: transparent;
border-radius: 4px;
height: 40px;
width: 80px;
font-size: 14px;
}
.btnBox button:last-of-type {
background: #71b900;
color: #fff;
border-radius: 4px;
height: 40px;
width: 80px;
font-size: 14px;
}
</style>



重置就是清除田字格當(dāng)前字,確定就將字保存為一張圖片base64排列在列表。
重簽就是刪除列表所有圖片,提交就是將多張圖合并為一張且傳給前一頁顯示。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
webpack安裝配置與常見使用過程詳解(結(jié)合vue)
這篇文章主要介紹了webpack安裝配置與常見使用過程,主要結(jié)合vue實(shí)現(xiàn),通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
分分鐘學(xué)會(huì)vue中vuex的應(yīng)用(入門教程)
本篇文章主要介紹了vue中vuex的應(yīng)用(入門教程),詳細(xì)的介紹了vuex.js和應(yīng)用方法,有興趣的可以了解一下2017-09-09
vue數(shù)據(jù)傳遞--我有特殊的實(shí)現(xiàn)技巧
這篇文章主要介紹了vue數(shù)據(jù)傳遞一些特殊梳理技巧,需要的朋友可以參考下2018-03-03
vue做移動(dòng)端適配最佳解決方案(親測(cè)有效)
這篇文章主要介紹了vue做移動(dòng)端適配最佳解決方案(親測(cè)有效),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
vue3?使用?vue3-video-play實(shí)現(xiàn)在線視頻播放
這篇文章主要介紹了vue3?使用?vue3-video-play?進(jìn)行在線視頻播放,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-06-06
Vue.js 的移動(dòng)端組件庫mint-ui實(shí)現(xiàn)無限滾動(dòng)加載更多的方法
下面小編就為大家分享一篇Vue.js 的移動(dòng)端組件庫mint-ui實(shí)現(xiàn)無限滾動(dòng)加載更多的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2017-12-12
關(guān)于vue項(xiàng)目部署后刷新網(wǎng)頁報(bào)404錯(cuò)誤解決
這篇文章主要介紹了關(guān)于vue項(xiàng)目部署后刷新網(wǎng)頁報(bào)404錯(cuò)誤解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07

