签名优化

This commit is contained in:
bb_pan 2025-08-29 11:21:10 +08:00
parent 21952c3eef
commit 461bb7fd56
2 changed files with 207 additions and 206 deletions

View File

@ -1,10 +1,19 @@
<template>
<view class="whole canvas-autograph flexc" @touchmove.prevent.stop @wheel.prevent.stop v-show="modelValue">
<canvas class="scroll-view" id="mycanvas" canvas-id="mycanvas"
<view
class="whole canvas-autograph flexc"
@touchmove.prevent.stop
@wheel.prevent.stop
v-show="modelValue"
>
<canvas
class="scroll-view"
id="mycanvas"
canvas-id="mycanvas"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
disable-scroll="true"/>
disable-scroll="true"
/>
<view class="fun-box">
<div class="hint">
<text class="rotate">请在下方空白区域横向书写签名</text>
@ -19,142 +28,112 @@
<text>取消</text>
</view>
</view>
<!-- 横向提示 -->
<view v-if="showToast" class="rotate-toast">
<text class="rotate-text">{{ toastMsg }}</text>
</view>
</view>
</template>
<script setup>
/*
使用如下
<canvas-autograph v-model="isCanvas" @complete="complete"/>
//
let isCanvas = ref(false)
//
const complete = e=>{
console.log(e)
}
*/
import { ref, reactive, watch, getCurrentInstance } from 'vue'
const emits = defineEmits(['update:modelValue', 'complete'])
const props = defineProps({
modelValue: Boolean,
})
const _this = getCurrentInstance()
watch(()=>props.modelValue,e=>{
// tabbar
//
},{
immediate:true, // false
})
let points = reactive([]) //
let canvaCtx = reactive(uni.createCanvasContext('mycanvas', _this)) //
//
canvaCtx.lineWidth = 6;
canvaCtx.lineWidth = 6
canvaCtx.lineCap = 'round'
canvaCtx.lineJoin = 'round'
//
let hasDrawn = ref(false)
//
const touchstart = e=>{
//
const showToast = ref(false)
const toastMsg = ref('')
const showRotateToast = (msg) => {
toastMsg.value = msg
showToast.value = true
setTimeout(() => (showToast.value = false), 2000)
}
//
const touchstart = (e) => {
let startX = e.changedTouches[0].x
let startY = e.changedTouches[0].y
let startPoint = { X: startX, Y: startY }
points.push(startPoint);
//
canvaCtx.beginPath();
points.push(startPoint)
canvaCtx.beginPath()
hasDrawn.value = true //
}
//
const touchmove = e=>{
//
const touchmove = (e) => {
let moveX = e.changedTouches[0].x
let moveY = e.changedTouches[0].y
let movePoint = { X: moveX, Y: moveY }
points.push(movePoint) //
let len = points.length
if(len>=2){
points.push(movePoint)
if (points.length >= 2) {
draw()
}
}
//
// const draw = ()=> {
// let point1 = points[0]
// let point2 = points[1]
// points.shift()
// canvaCtx.moveTo(point1.X, point1.Y)
// canvaCtx.lineTo(point2.X, point2.Y)
// canvaCtx.stroke()
// canvaCtx.draw(true)
// }
//
const draw = () => {
if (points.length < 2) return;
canvaCtx.beginPath();
canvaCtx.moveTo(points[0].X, points[0].Y);
if (points.length < 2) return
canvaCtx.beginPath()
canvaCtx.moveTo(points[0].X, points[0].Y)
for (let i = 1; i < points.length; i++) {
canvaCtx.lineTo(points[i].X, points[i].Y);
canvaCtx.lineTo(points[i].X, points[i].Y)
}
canvaCtx.stroke();
canvaCtx.draw(true);
//
points = [points[points.length - 1]]; //
canvaCtx.stroke()
canvaCtx.draw(true)
points = [points[points.length - 1]]
}
//
const touchend = e=>{
points = [];
//
const touchend = () => {
points = []
}
//
// const clear = ()=>{
// return uni.getSystemInfo()
// .then(res=>{
// canvaCtx.clearRect(0, 0, res.windowWidth, res.windowHeight);
// canvaCtx.draw(true);
// return res
// })
// .catch(err=>{
// // console.log(err);
// })
// }
const clear = () => {
return new Promise((resolve, reject) => {
uni.createSelectorQuery()
uni
.createSelectorQuery()
.in(_this)
.select('#mycanvas') // id canvas
.fields({ size: true, rect: true }, data => {
.select('#mycanvas')
.fields({ size: true, rect: true }, (data) => {
if (!data) {
reject('Canvas not found')
return
}
const { width, height } = data
// canvas
canvaCtx.clearRect(0, 0, width, height)
canvaCtx.draw(true)
hasDrawn.value = false
resolve()
})
.exec()
})
}
//
const confirm = () => {
uni.canvasToTempFilePath({ canvasId: 'mycanvas', }, _this, _this.parent)
.then(res=>{
console.log(res.tempFilePath);
if (!hasDrawn.value) {
showRotateToast('请先签名再确认')
return
}
uni.canvasToTempFilePath({ canvasId: 'mycanvas' }, _this, _this.parent).then((res) => {
emits('complete', res.tempFilePath)
cancel()
})
}
//
const cancel = () => {
clear().then(res=>emits('update:modelValue',false))
clear().then(() => emits('update:modelValue', false))
}
</script>
<style scoped lang="scss">
@ -169,23 +148,21 @@ const clear = () => {
.scroll-view {
width: calc(100% - 120rpx);
height: 99.6%;
background-color: #FFFFFF;
background-color: #ffffff;
border: 2px solid #333;
}
.fun-box {
position: absolute;
height: 90rpx;
right: 0;
bottom: 0px;
height: auto;
display: flex;
flex-direction: column;
.fun-box-btn {
width: 100rpx;
height: 160rpx;
color: #FFFFFF;
color: #ffffff;
border-radius: 20rpx;
border: 1rpx solid #C0C0C0;
border: 1rpx solid #c0c0c0;
display: flex;
align-items: center;
justify-content: center;
@ -195,14 +172,14 @@ const clear = () => {
}
.clear {
color: #909399;
background-color: #F4F4F5;
background-color: #f4f4f5;
}
.confirm {
background-color: #409EFF;
background-color: #409eff;
margin: 3px 0;
}
.cancel {
background-color: #F67D7D;
background-color: #f67d7d;
}
.hint {
width: 100rpx;
@ -210,19 +187,43 @@ const clear = () => {
display: flex;
align-items: center;
justify-content: center;
color: #F67D7D;
color: #f67d7d;
background: transparent;
margin-bottom: 150rpx;
.rotate {
display: inline-block;
transform: rotate(90deg);
transform-origin: center;
white-space: nowrap;
font-size: 33rpx;
}
}
}
}
/* 横向提示样式 */
.rotate-toast {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.75);
padding: 20rpx;
border-radius: 24rpx;
z-index: 999;
/* 重点调整 */
width: 100rpx; /* 宽度只需少量,留给旋转文字 */
min-height: 400rpx; /* 高度拉长,保证横向文字能完整显示 */
display: flex;
align-items: center;
justify-content: center;
}
.rotate-text {
color: #fff;
font-size: 36rpx;
transform: rotate(90deg);
display: inline-block;
white-space: nowrap; /* 保证一行显示 */
}
</style>

View File

@ -8,7 +8,7 @@
个人电子签名维护,支持手机拍照上传图片以及手写签名推荐使用手写签名请横向书写签名
</div>
<div class="btns">
<button class="btn" type="primary" @click="handlePhoto">拍照/上传</button>
<!-- <button class="btn" type="primary" @click="handlePhoto">拍照/上传</button> -->
<button class="btn" type="primary" @click="open">手写签名</button>
</div>
<miliu-autograph v-model="isCanvas" @complete="complete"></miliu-autograph>
@ -327,10 +327,10 @@ const uploadSignUrl = async (url) => {
margin: 10rpx;
border-radius: 20rpx;
.btn {
width: 40%;
&:first-child {
width: 100%;
/* &:first-child {
margin-right: 20px;
}
} */
}
}
.signature-page {