在线签名
代码实现
<template>
<h3>在线签名</h3>
<div ref="mainboard" class="container">
<div class="mianboard" :style="{
width: data.size.width + 'px',
height: data.size.height + 'px'
}">
<!-- 主画板 -->
<canvas id="main" :width="data.size.width" :height="data.size.height"></canvas>
<!-- 签名绘制浮层画板 -->
<div ref="floatboard" v-show="show" class="floatboard" :style="{
left: left + 'px',
top: top + 'px'
}" @mousedown="floatMouseDown">
<canvas id="float" width="200" height="80"></canvas>
</div>
<div class="sab">
<button @click="save">保存</button>
<button @click="backInit">清除</button>
</div>
</div>
<div class="signboard">
<!-- 签名画板 -->
<canvas id="sign" width="600" height="400" @mousedown="signMousedown" @mousemove="signMousemove"
@mouseup="signMouseup"></canvas>
<div>
<button @click="clearSign">清除</button>
<button @click="sendSignToFloat">确认</button>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
/* 画板相关变量 */
// 全局变量
let float = null;
let floatCtx = null;
let sign = null;
let signCtx = null;
let main = null;
let mainCtx = null;
let left = ref(0);
let top = ref(0)
let show = ref(false)
// 后端数据
const data = {
baseUrl: 'http://localhost:8080/img/%E6%8A%A5%E9%94%80%E5%8D%95.cd8b07df.jpg',
size: {
width: 600,
height: 400
}
}
/* 主画板和其相关变量 */
onMounted(() => {
// 获取主画板并且初始化为canvas画布
main = document.getElementById('main');
mainCtx = main.getContext('2d');
// 绘制合同图片为背景
const img = new Image();
img.src = data.baseUrl;
img.onload = function () {
mainCtx.drawImage(img, 0, 0, data.size.width, data.size.height);
}
})
// 保存签名
function save() {
mainCtx.drawImage(float, left.value, top.value, 200, 80);
// 将画板内容转换为 base64数据
let base = main.toDataURL();
show.value = false;
}
// 清除签名
function backInit() {
mainCtx.clearRect(0, 0, data.size.width, data.size.height)
// 绘制合同图片为背景
const img = new Image();
img.src = data.baseUrl;
img.onload = function () {
mainCtx.drawImage(img, 0, 0, data.size.width, data.size.height);
}
show.value = false;
left.value = 0;
top.value = 0
}
/* 签名版和其相关变量 */
let canSign = false;
onMounted(() => {
// 获取签名板并且初始化为canvas画布
sign = document.getElementById('sign');
signCtx = sign.getContext('2d');
})
// 监听鼠标按下事件
function signMousedown(e) {
canSign = true;
// 重新绘制
signCtx.beginPath()
signCtx.moveTo(e.offsetX, e.offsetY);
// 设置线条样式
signCtx.lineWidth = 5;
signCtx.strokeStyle = "red";
}
// 监听鼠标移动事件
function signMousemove(e) {
if (canSign) {
signCtx.lineTo(e.offsetX, e.offsetY);
signCtx.stroke()
}
}
// 监听鼠标松开事件
function signMouseup() {
canSign = false
}
// 清除画板
function clearSign() {
signCtx.clearRect(0, 0, sign.width, sign.height)
}
// 确认签名
function sendSignToFloat() {
floatCtx.drawImage(sign, 0, 0, 200, 80);
show.value = true
}
/* 签名悬浮板相关逻辑 */
onMounted(() => {
// 获取悬浮板并且初始化为canvas画布
float = document.getElementById('float');
floatCtx = float.getContext('2d');
})
/* 拖拽相关代码 */
// 鼠标按下点和推拽元素的距离
let distanceX = 0;
let distanceY = 0;
let mainboard = ref()
let floatboard = ref()
function floatMouseDown(e) {
/* pageX 是鼠标点距离屏幕X轴的距离
offsetLeft 是自身元素左边距和上一个定位元素的距离 */
distanceX = e.pageX - mainboard.value.offsetLeft - floatboard.value.offsetLeft;
distanceY = e.pageY - mainboard.value.offsetTop - floatboard.value.offsetTop;
function move(e) {
left.value = e.pageX - mainboard.value.offsetLeft - distanceX;
top.value = e.pageY - mainboard.value.offsetTop - distanceY
}
document.addEventListener('mousemove', move, false)
document.addEventListener('mouseup', () => {
// 移除监听事件
document.removeEventListener('mousemove', move)
}, false)
}
</script>
<style scoped>
.container {
display: flex;
position: relative;
}
.mianboard {
border: 1px solid;
margin-right: 20px;
}
.floatboard {
position: absolute;
border: 1px solid
}
.sab{
margin-top: 10px;
}
.signboard {
display: flex;
flex-direction: column;
height: 400px;
border: 2px dashed #8e9bf1;
}
.signboard div {
margin-top: 10px;
}
</style>