效果图
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/625ab83ed5e52aabfb47a276125ea6ea.png)
参数配置
![参数配置](https://i-blog.csdnimg.cn/blog_migrate/a7e1618b93f1d8bb943bec5b22ef67ee.png)
方法
方法名 | 方法说明 |
---|
confirm | 点击确认触发,返回canvas生成图片的图片路径 |
close | 组件关闭时触发 |
uniapp组件代码
<template>
<view class="commRoot" :class="commonShow" :style="'z-index:'+zIndex+';'">
<view class="commContentBox">
<view class="titleBarBox ">
<view class="w-25 d-flex justify-content-space-between">
<view class="btn" @click="commonShow='hidden'">
取消
</view>
<view class="btn" @click="clearRect()">
清空
</view>
</view>
<view class="w-50 d-flex justify-content-center align-items-center"
style="font-weight: bolder;font-size:40rpx;">
{{title}}
</view>
<view class="w-25 d-flex justify-content-flex-end">
<view @click="submit" class="btn" :style="{
'background-color': confirmBtnBgColor,
'color':confirmBtnColor
}">
确定
</view>
</view>
</view>
<canvas @touchstart="canvasTouchStart" @touchmove="canvasTouchMove" @touchend="canvasTouchEnd"
canvas-id="canvasTag" :style="{width: canvasW+'px', height: canvasH+'px' }"></canvas>
</view>
</view>
</template>
<script>
let ctx = null;
let lastX, lastY;
export default {
name: "signComponentByDan",
props: {
zIndex: {
type: [String, Number],
default: 10086
},
title: {
type: String,
default: "合同签名"
},
show: {
type: Boolean,
default: false
},
lineW: {
type: [String, Number],
default: 1
},
lineColor: {
type: String,
default: "#000000"
},
confirmBtnBgColor: {
type: String,
default: "#307ECE"
},
confirmBtnColor: {
type: String,
default: "#fff"
}
},
watch: {
show: function(v) {
if (v) {
this.commonShow = "show";
}else{
this.commonShow = "hidden";
}
},
commonShow:function(v){
if(v=='hidden'){
console.log(v)
this.$emit('close',this.commonShow)
}
}
},
computed: {
windowHeight: function() {
return uni.getSystemInfoSync().windowHeight;
},
windowWidth: function() {
return uni.getSystemInfoSync().windowWidth;
},
canvasW: function() {
return this.windowWidth - 50
},
canvasH: function() {
return this.windowHeight
}
},
data() {
return {
commonShow: "hidden",
drawing: false,
haveContent: false,
};
},
mounted() {
ctx = uni.createCanvasContext('canvasTag', this)
},
methods: {
loadFile(url) {
return new Promise((resolve, reject) => {
uni.downloadFile({
url: url,
header: {
'content-type': 'application/x-www-form-urlencoded;charset=UTF-8'
},
success: (res) => {
resolve(res)
}
});
})
},
submit() {
if (this.haveContent) {
uni.showLoading({
title:"保存中..",
})
uni.canvasToTempFilePath({
canvasId: 'canvasTag',
success: toTempFileRes => {
uni.hideLoading()
console.log(toTempFileRes)
console.log(toTempFileRes.errMsg)
this.image = toTempFileRes.tempFilePath;
this.commonShow="hidden";
this.$emit('confirm',this.image)
}
},this)
} else {
uni.showToast({
title: "请签名!",
icon: "none"
})
}
},
clearRect() {
this.haveContent = false;
ctx.clearRect(0, 0, this.canvasW, this.canvasH)
ctx.draw()
},
canvasTouchStart(e) {
let x = e.touches[0].x;
let y = e.touches[0].y;
this.drawLine(x, y, false)
},
canvasTouchMove(e) {
let x = e.touches[0].x;
let y = e.touches[0].y;
this.drawLine(x, y, true)
},
canvasTouchEnd(e) {
let x = e.changedTouches[0].x;
let y = e.changedTouches[0].y;
this.drawLine(x, y, false)
},
drawLine(x, y, isT) {
if (isT) {
ctx.beginPath();
ctx.lineWidth = this.lineW;
ctx.strokeStyle = this.lineColor;
ctx.lineCap = 'round'
ctx.lineJoin = "round";
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.stroke();
ctx.closePath();
ctx.draw(true, () => {
this.haveContent = true;
})
}
lastX = x;
lastY = y;
}
}
}
</script>
<style lang="less">
page {
height: 100vh;
overflow: hidden;
}
.commRoot {
width: 100vw;
height: 100vh;
position: fixed;
left: 0rpx;
transition: top 0.7s;
background-color: white;
}
.show {
top: 0vh;
}
.hidden {
top: -100vh;
}
.titleBarBox {
width: 100vh;
display: flex;
box-sizing: border-box;
border-bottom: 1rpx solid #ddd;
justify-content: space-between;
padding: 0rpx 30rpx;
height: 50px;
align-items: center;
background-color: #fff;
transform-origin: 50% 50%;
transform: rotate(90deg);
right: calc((50px - 100vh) / 2);
position: absolute;
top: calc((100vh - 50px) / 2);
}
.commContentBox {
width: 100vh;
height: 100vw;
background-color: white;
}
.w-25 {
width: 25%;
}
.w-30 {
width: 30%;
}
.w-50 {
width: 50%;
}
.d-flex {
display: flex;
}
.justify-content-space-between {
justify-content: space-between;
}
.justify-content-center {
justify-content: center;
}
.justify-content-flex-end {
justify-content: flex-end;
}
.align-items-center {
align-items: center;
}
.btn {
padding: 15rpx 40rpx;
border-radius: 10rpx;
white-space: nowrap;
border: 1rpx solid #ddd;
}
</style>