|
|
<template>
|
|
|
<view class="sign">
|
|
|
<view class="sign-bkg">
|
|
|
<view class="sign-bkg__word">
|
|
|
<span>签</span>
|
|
|
<span>名</span>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="sign-pic">
|
|
|
<!-- <image src="/static/cloud.png" class="sign-pic__cloud" mode="widthFix"></image>-->
|
|
|
<image class="sign-pic__city" :src="require('@/static/city.png')" mode="widthFix" />
|
|
|
</view>
|
|
|
|
|
|
<view class="sign-cnv">
|
|
|
<l-signature disableScroll backgroundColor="#ddd" ref="signatureRef" :penColor="options.penColor"
|
|
|
:backgroundColor="options.backgroundColor" :penSize="options.penSize" :openSmooth="options.openSmooth">
|
|
|
</l-signature>
|
|
|
</view>
|
|
|
|
|
|
<view class="sign-btn">
|
|
|
<view class="sign-btn__reset" @click="$u.throttle(onClick('clear'))">重置</view>
|
|
|
<view class="sign-btn__confirm" @click="$u.throttle(onClick('save'))">确认</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
import {
|
|
|
base64ToFile
|
|
|
} from '@/common/util.js'
|
|
|
import {
|
|
|
ROOTPATH
|
|
|
} from '@/common/config.js'
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
url: '',
|
|
|
options: {
|
|
|
penColor: '#000',
|
|
|
penSize: 16,
|
|
|
openSmooth: true,
|
|
|
backgroundColor: 'rgba(0,0,0,0)'
|
|
|
},
|
|
|
}
|
|
|
},
|
|
|
methods: {
|
|
|
//src - 图片路径,deg旋转角度
|
|
|
rotateBase64Img(src, edg) {
|
|
|
return new Promise((resolve, reject) => {
|
|
|
const canvas = document.createElement('canvas')
|
|
|
const ctx = canvas.getContext('2d')
|
|
|
let imgW // 图片宽度
|
|
|
let imgH // 图片高度
|
|
|
let size // canvas初始大小
|
|
|
if (edg % 90 != 0) {
|
|
|
console.error('旋转角度必须是90的倍数!')
|
|
|
}
|
|
|
(edg < 0) && (edg = (edg % 360) + 360)
|
|
|
const quadrant = (edg / 90) % 4 // 旋转象限
|
|
|
const cutCoor = {
|
|
|
sx: 0,
|
|
|
sy: 0,
|
|
|
ex: 0,
|
|
|
ey: 0
|
|
|
} // 裁剪坐标
|
|
|
const image = new Image()
|
|
|
image.crossOrigin = 'anonymous'
|
|
|
image.src = src
|
|
|
image.onload = () => {
|
|
|
imgW = image.width
|
|
|
imgH = image.height
|
|
|
size = imgW > imgH ? imgW : imgH
|
|
|
canvas.width = size * 2
|
|
|
canvas.height = size * 2
|
|
|
switch (quadrant) {
|
|
|
case 0:
|
|
|
cutCoor.sx = size
|
|
|
cutCoor.sy = size
|
|
|
cutCoor.ex = size + imgW
|
|
|
cutCoor.ey = size + imgH
|
|
|
break
|
|
|
case 1:
|
|
|
cutCoor.sx = size - imgH
|
|
|
cutCoor.sy = size
|
|
|
cutCoor.ex = size
|
|
|
cutCoor.ey = size + imgW
|
|
|
break
|
|
|
case 2:
|
|
|
cutCoor.sx = size - imgW
|
|
|
cutCoor.sy = size - imgH
|
|
|
cutCoor.ex = size
|
|
|
cutCoor.ey = size
|
|
|
break
|
|
|
case 3:
|
|
|
cutCoor.sx = size
|
|
|
cutCoor.sy = size - imgW
|
|
|
cutCoor.ex = size + imgH
|
|
|
cutCoor.ey = size + imgW
|
|
|
break
|
|
|
}
|
|
|
ctx.translate(size, size)
|
|
|
ctx.rotate(edg * Math.PI / 180)
|
|
|
ctx.drawImage(image, 0, 0)
|
|
|
var imgData = ctx.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey)
|
|
|
if (quadrant % 2 == 0) {
|
|
|
canvas.width = imgW
|
|
|
canvas.height = imgH
|
|
|
} else {
|
|
|
canvas.width = imgH
|
|
|
canvas.height = imgW
|
|
|
}
|
|
|
ctx.putImageData(imgData, 0, 0)
|
|
|
// 获取旋转后的base64图片
|
|
|
resolve(canvas.toDataURL())
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
|
|
|
onClick(type) {
|
|
|
if (type == 'openSmooth') {
|
|
|
this.openSmooth = !this.openSmooth
|
|
|
return
|
|
|
}
|
|
|
if (type == 'save') {
|
|
|
this.$refs.signatureRef.canvasToTempFilePath({
|
|
|
success: (res) => {
|
|
|
// 是否为空画板 无签名
|
|
|
if (res.isEmpty) {
|
|
|
uni.showToast({
|
|
|
title: '请签名',
|
|
|
icon: 'none'
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
// 生成图片的临时路径
|
|
|
// app | H5 | 微信小程序 生成的是base64
|
|
|
if (res.tempFilePath) {
|
|
|
//this.$u.vuex('vuex_sign_base64', res.tempFilePath)
|
|
|
this.rotateBase64Img(res.tempFilePath, -90).then(res => {
|
|
|
this.$u.vuex('vuex_sign_base64', res)
|
|
|
let form = new FormData()
|
|
|
form.append('file', base64ToFile(res, 'sign'))
|
|
|
form.append('active_tag', 'map_point')
|
|
|
form.append('activity_list_id', 7)
|
|
|
form.append('token',this.vuex_token)
|
|
|
let xhr = new XMLHttpRequest()
|
|
|
xhr.open('post', `${ROOTPATH}/api/mobile/upload-file`)
|
|
|
|
|
|
xhr.onreadystatechange = () => {
|
|
|
if (xhr.status === 200 && xhr.readyState ===
|
|
|
4) {
|
|
|
let val = JSON.parse(xhr.responseText);
|
|
|
console.log(val);
|
|
|
this.$u.api.savePoster({
|
|
|
upload_id: val.id,
|
|
|
type: 2
|
|
|
}).then(_ => {
|
|
|
uni.navigateTo({
|
|
|
url: `/pages/certificate/certificate`
|
|
|
})
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
xhr.send(form)
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
return
|
|
|
}
|
|
|
if (this.$refs.signatureRef)
|
|
|
this.$refs.signatureRef[type]()
|
|
|
},
|
|
|
},
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
@media screen and (orientation: portrait) {
|
|
|
.sign {
|
|
|
height: 100vh;
|
|
|
width: 100vw;
|
|
|
|
|
|
&-pic {
|
|
|
width: 100vh;
|
|
|
display: flex;
|
|
|
align-items: flex-end;
|
|
|
transform: rotate(90deg) translateX(0%) translateY(-100%);
|
|
|
transform-origin: 0 0;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
&__cloud {
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
&__city {
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
&-bkg {
|
|
|
background-color: #FEFAEE;
|
|
|
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
|
|
|
&__word {
|
|
|
width: 390rpx;
|
|
|
font-size: 128rpx;
|
|
|
font-weight: 400;
|
|
|
color: #BBB6B2;
|
|
|
opacity: 0.3;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
transform: rotate(90deg) translateX(-50%) translateY(calc(-100% - 426rpx));
|
|
|
transform-origin: 0 0;
|
|
|
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
&-cnv {
|
|
|
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
}
|
|
|
|
|
|
&-btn {
|
|
|
display: flex;
|
|
|
transform: rotate(90deg) translateX(-50%) translateY(-100%);
|
|
|
transform-origin: 0% 0%;
|
|
|
|
|
|
margin-left: 112rpx;
|
|
|
z-index: 99999;
|
|
|
position: fixed;
|
|
|
top: 50%;
|
|
|
|
|
|
&__reset {
|
|
|
width: 200rpx;
|
|
|
height: 66rpx;
|
|
|
background: #FEFAEE;
|
|
|
border: 4rpx solid #CA3F32;
|
|
|
border-radius: 34rpx;
|
|
|
font-size: 26rpx;
|
|
|
font-weight: 400;
|
|
|
color: #B61F2E;
|
|
|
line-height: 58rpx;
|
|
|
text-align: center;
|
|
|
|
|
|
margin-right: 52rpx;
|
|
|
}
|
|
|
|
|
|
&__confirm {
|
|
|
font-size: 26rpx;
|
|
|
font-weight: 400;
|
|
|
color: #FFFFFF;
|
|
|
width: 200rpx;
|
|
|
height: 66rpx;
|
|
|
background: linear-gradient(0deg, #E16055, #C54439);
|
|
|
border-radius: 34rpx;
|
|
|
line-height: 66rpx;
|
|
|
text-align: center;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
@media screen and (orientation: landscape) {
|
|
|
.sign {
|
|
|
height: 100vh;
|
|
|
width: 100vw;
|
|
|
|
|
|
&-pic {
|
|
|
width: 100vw;
|
|
|
display: flex;
|
|
|
align-items: flex-end;
|
|
|
|
|
|
position: absolute;
|
|
|
bottom: 0;
|
|
|
|
|
|
&__cloud {
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
&__city {
|
|
|
flex: 1;
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
&-bkg {
|
|
|
background-color: #FEFAEE;
|
|
|
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
|
|
|
&__word {
|
|
|
width: 18vw;
|
|
|
font-size: 6vw;
|
|
|
font-weight: 400;
|
|
|
color: #BBB6B2;
|
|
|
opacity: 0.3;
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
transform: translate(-50%, -50%);
|
|
|
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
&-cnv {
|
|
|
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
right: 0;
|
|
|
bottom: 0;
|
|
|
}
|
|
|
|
|
|
&-btn {
|
|
|
display: flex;
|
|
|
transform: translateX(-50%);
|
|
|
|
|
|
z-index: 99999;
|
|
|
position: fixed;
|
|
|
bottom: 8vh;
|
|
|
left: 50%;
|
|
|
|
|
|
&__reset {
|
|
|
width: 16.6vw;
|
|
|
height: 5.2vw;
|
|
|
background: #FEFAEE;
|
|
|
border: 0.4vw solid #CA3F32;
|
|
|
border-radius: 34rpx;
|
|
|
font-size: 2.6vw;
|
|
|
font-weight: 400;
|
|
|
color: #B61F2E;
|
|
|
text-align: center;
|
|
|
line-height: 5.2vw;
|
|
|
box-sizing: content-box;
|
|
|
|
|
|
margin-right: 48rpx;
|
|
|
}
|
|
|
|
|
|
&__confirm {
|
|
|
font-size: 2.6vw;
|
|
|
font-weight: 400;
|
|
|
color: #FFFFFF;
|
|
|
width: 17.4vw;
|
|
|
height: 6vw;
|
|
|
background: linear-gradient(0deg, #E16055, #C54439);
|
|
|
border-radius: 34rpx;
|
|
|
text-align: center;
|
|
|
line-height: 6vw;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</style>
|