278 lines
7.9 KiB
Vue
278 lines
7.9 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="box">
|
|||
|
|
<canvas v-if="showCanvas" id="canvas" canvas-id="canvas" style="width: 100vw;background-color: green;" :style="`height:${canvasHeight}px`" @touchstart="startDraw" @touchmove="drawing" @@touchend="endDraw"></canvas>
|
|||
|
|
|
|||
|
|
<cover-view class="tipTxt">请在空白处横屏签名</cover-view>
|
|||
|
|
|
|||
|
|
<view class="btn">
|
|||
|
|
<uv-button size="large" style="width: 50%;" @tap="clearSign">重 签</uv-button>
|
|||
|
|
<uv-button type="primary" size="large" class="mainBtn" style="width: 50%;" @tap="confirm">完 成</uv-button>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script setup>
|
|||
|
|
import { onReady, onUnload } from '@dcloudio/uni-app';
|
|||
|
|
import { ref, nextTick } from 'vue';
|
|||
|
|
import { pathToBase64, base64ToPath } from './index.js'
|
|||
|
|
import { uploadImg } from "@/api/upload"
|
|||
|
|
|
|||
|
|
const btnHeight = ref(null)
|
|||
|
|
const BoxHeight = ref(null)
|
|||
|
|
const canvasWidth = ref(null)
|
|||
|
|
const canvasHeight = ref(null)
|
|||
|
|
const showCanvas = ref(false)
|
|||
|
|
|
|||
|
|
const signFlag = ref(false)
|
|||
|
|
|
|||
|
|
const getBtnHeight = () => {
|
|||
|
|
const query = uni.createSelectorQuery().in(this);
|
|||
|
|
// 选择要查询的元素,使用元素ID或类名
|
|||
|
|
query.select('.btn').boundingClientRect(data => {
|
|||
|
|
btnHeight.value = data.height
|
|||
|
|
}).select('.box').boundingClientRect(res => {
|
|||
|
|
// console.log('元素高度:', res);
|
|||
|
|
// BoxHeight.value = res.height
|
|||
|
|
// canvasWidth.value = res.width
|
|||
|
|
}).exec(() => {
|
|||
|
|
// 确保两个查询都完成后再初始化画布
|
|||
|
|
if (btnHeight.value && BoxHeight.value && canvasWidth.value) {
|
|||
|
|
console.log("获取",BoxHeight.value,btnHeight.value);
|
|||
|
|
|
|||
|
|
canvasHeight.value = BoxHeight.value - btnHeight.value
|
|||
|
|
showCanvas.value = true
|
|||
|
|
// 等待DOM更新完成后再初始化Canvas
|
|||
|
|
nextTick(() => {
|
|||
|
|
initCanvas();
|
|||
|
|
});
|
|||
|
|
} else {
|
|||
|
|
console.error('获取元素尺寸失败,无法初始化画布');
|
|||
|
|
}
|
|||
|
|
}); // 执行查询
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
let canvasContext = null
|
|||
|
|
const initCanvas = () => {
|
|||
|
|
console.log(canvasWidth.value, canvasHeight.value)
|
|||
|
|
canvasContext = uni.createCanvasContext('canvas');
|
|||
|
|
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
|
|||
|
|
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
|
|||
|
|
canvasContext.draw(true)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const startX = ref(null)
|
|||
|
|
const startY = ref(null)
|
|||
|
|
const startDraw = (e) => {
|
|||
|
|
startX.value = e.touches[0].x
|
|||
|
|
startY.value = e.touches[0].y
|
|||
|
|
canvasContext.beginPath(); // 开始创建一个路径
|
|||
|
|
signFlag.value = true
|
|||
|
|
}
|
|||
|
|
const endDraw = (e) => {
|
|||
|
|
startX.value = 0
|
|||
|
|
startY.value = 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const drawing = (e) => {
|
|||
|
|
let temX = e.touches[0].x;
|
|||
|
|
let temY = e.touches[0].y;
|
|||
|
|
canvasContext.moveTo(startX.value, startY.value)
|
|||
|
|
canvasContext.lineTo(temX, temY)
|
|||
|
|
canvasContext.setStrokeStyle('#000') // 文字颜色
|
|||
|
|
canvasContext.setLineWidth(4) // 文字宽度
|
|||
|
|
canvasContext.setLineCap('round') // 文字圆角
|
|||
|
|
canvasContext.stroke() // 文字绘制
|
|||
|
|
startX.value = temX
|
|||
|
|
startY.value = temY
|
|||
|
|
canvasContext.draw(true) // 文字绘制到画布中
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const clearSign = () => {
|
|||
|
|
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
|
|||
|
|
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
|
|||
|
|
canvasContext.draw(true) // 文字绘制到画布中
|
|||
|
|
signFlag.value = false
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const confirm = () => {
|
|||
|
|
// 确认按钮事件
|
|||
|
|
if (!signFlag.value) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '请签名后再点击确定',
|
|||
|
|
icon: 'none',
|
|||
|
|
duration: 2000
|
|||
|
|
})
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '确认',
|
|||
|
|
content: '确认签名无误吗',
|
|||
|
|
showCancel: true,
|
|||
|
|
success: async ({ confirm }) => {
|
|||
|
|
if (confirm) {
|
|||
|
|
let tempFile
|
|||
|
|
// if (this.horizontal) {
|
|||
|
|
tempFile = await saveHorizontalCanvas()
|
|||
|
|
// } else {
|
|||
|
|
// tempFile = await this.saveCanvas()
|
|||
|
|
// }
|
|||
|
|
console.log(tempFile, "tempFile")
|
|||
|
|
const base64 = await pathToBase64(tempFile)
|
|||
|
|
const path = await base64ToPath(base64)
|
|||
|
|
console.log(path, "path")
|
|||
|
|
const res = await uploadImg(path, {});
|
|||
|
|
uni.navigateBack();
|
|||
|
|
uni.$emit('getSignImg', { base64, path, url: res.url });
|
|||
|
|
// uploadImg(path, {}).then(res=>{
|
|||
|
|
// console.log(base64, path, res.url, "打印")
|
|||
|
|
// let url = res.url
|
|||
|
|
// uni.$emit('getSignImg', { base64, path, url })
|
|||
|
|
// uni.navigateBack()
|
|||
|
|
// })
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
const saveHorizontalCanvas = async () => {
|
|||
|
|
return await new Promise((resolve, reject) => {
|
|||
|
|
uni.canvasToTempFilePath(
|
|||
|
|
{
|
|||
|
|
canvasId: 'canvas',
|
|||
|
|
fileType: "png", // 只支持png和jpg
|
|||
|
|
success: (res) => {
|
|||
|
|
if (!res.tempFilePath) {
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '提示',
|
|||
|
|
content: '保存签名失败',
|
|||
|
|
showCancel: false
|
|||
|
|
})
|
|||
|
|
return
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// #ifdef APP
|
|||
|
|
uni.compressImage({
|
|||
|
|
src: res.tempFilePath,
|
|||
|
|
quality: 100, // 范围 0 - 100
|
|||
|
|
rotate: 270,
|
|||
|
|
success: (r) => {
|
|||
|
|
console.log('==== compressImage :', r)
|
|||
|
|
resolve(r.tempFilePath)
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
// #endif
|
|||
|
|
|
|||
|
|
// #ifndef APP
|
|||
|
|
// uni.getImageInfo({
|
|||
|
|
// src: res.tempFilePath,
|
|||
|
|
// success: (r) => {
|
|||
|
|
// // console.log('==== getImageInfo :', r)
|
|||
|
|
// // 将signCanvas的内容复制到hsignCanvas中
|
|||
|
|
// const hcanvasCtx = uni.createCanvasContext('hsignCanvas', this)
|
|||
|
|
// // 横屏宽高互换
|
|||
|
|
// hcanvasCtx.translate(this.canvasHeight / 2, this.canvasWidth / 2)
|
|||
|
|
// hcanvasCtx.rotate(Math.PI * (-90 / 180))
|
|||
|
|
// hcanvasCtx.drawImage(
|
|||
|
|
// r.path,
|
|||
|
|
// -this.canvasWidth / 2,
|
|||
|
|
// -this.canvasHeight / 2,
|
|||
|
|
// this.canvasWidth,
|
|||
|
|
// this.canvasHeight
|
|||
|
|
// )
|
|||
|
|
// hcanvasCtx.draw(false, async () => {
|
|||
|
|
// const hpathRes = await uni.canvasToTempFilePath(
|
|||
|
|
// {
|
|||
|
|
// canvasId: 'hsignCanvas',
|
|||
|
|
// fileType: this.expFile.fileType, // 只支持png和jpg
|
|||
|
|
// quality: this.expFile.quality // 范围 0 - 1
|
|||
|
|
// },
|
|||
|
|
// this
|
|||
|
|
// )
|
|||
|
|
// let tempFile = ''
|
|||
|
|
// if (Array.isArray(hpathRes)) {
|
|||
|
|
// hpathRes.some((item) => {
|
|||
|
|
// if (item) {
|
|||
|
|
// tempFile = item.tempFilePath
|
|||
|
|
// return
|
|||
|
|
// }
|
|||
|
|
// })
|
|||
|
|
// } else {
|
|||
|
|
// tempFile = hpathRes.tempFilePath
|
|||
|
|
// }
|
|||
|
|
// resolve(tempFile)
|
|||
|
|
// })
|
|||
|
|
// }
|
|||
|
|
// })
|
|||
|
|
// #endif
|
|||
|
|
},
|
|||
|
|
fail: (err) => {
|
|||
|
|
console.log('图片生成失败:' + err)
|
|||
|
|
resolve(false)
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
this
|
|||
|
|
)
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|
|||
|
|
onReady(() => {
|
|||
|
|
// uni.showLoading({
|
|||
|
|
// title: '正在加载,请稍后...',
|
|||
|
|
// mask: true
|
|||
|
|
// })
|
|||
|
|
// 页面加载完成后设置横屏
|
|||
|
|
// plus.screen.lockOrientation('landscape-primary')
|
|||
|
|
// nextTick(() => {
|
|||
|
|
// getBtnHeight();
|
|||
|
|
// });
|
|||
|
|
// setTimeout(() => {
|
|||
|
|
// uni.hideLoading();
|
|||
|
|
uni.getSystemInfo({
|
|||
|
|
success: function (res) {
|
|||
|
|
console.log(res)
|
|||
|
|
BoxHeight.value = res.windowHeight
|
|||
|
|
canvasWidth.value = res.windowWidth
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
getBtnHeight();
|
|||
|
|
// }, 1500);
|
|||
|
|
// nextTick(() => {
|
|||
|
|
// getBtnHeight();
|
|||
|
|
// });
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
|
|||
|
|
onUnload(() => {
|
|||
|
|
// 页面卸载时恢复竖屏
|
|||
|
|
// plus.screen.lockOrientation('portrait-primary');
|
|||
|
|
})
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style scoped lang="scss">
|
|||
|
|
.box {
|
|||
|
|
position: relative;
|
|||
|
|
width: 100vw;
|
|||
|
|
height: 100vh;
|
|||
|
|
|
|||
|
|
.tipTxt{
|
|||
|
|
position: absolute;
|
|||
|
|
top: 10rpx;
|
|||
|
|
left: 10rpx;
|
|||
|
|
color: #999;
|
|||
|
|
font-size: 44rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.btn {
|
|||
|
|
position: fixed;
|
|||
|
|
width: 100vw;
|
|||
|
|
bottom: 0;
|
|||
|
|
z-index: 99;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</style>
|