<template>
<view class="signature-main" style="z-index: 99">
<img v-if="!edit" :src="oldLines.value" alt="" />
<div class="edit-con" v-else>
<view class="sign">
<view class="content">
<text class="iconfont icon-shuaxin"></text>
<text @click="clearSignature">重新签名</text>
</view>
</view>
<div class="canvas-con">
<canvas
disable-scroll="true"
class="signature"
:class="cid"
:canvas-id="cid"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
></canvas>
</div>
<view class="placeholder" v-if="ctrl && !ctrl.getValue()"
>请在此处签名</view
>
</div>
</view>
</template>
<script>
import { getUUID } from '@/utils';
let _keyStr =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var _utf8_encode = function (string) {
string = string.replace(/\r\n/g, '\n');
var utftext = '';
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n);
if (c < 128) {
utftext += String.fromCharCode(c);
} else if (c > 127 && c < 2048) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
} else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}
}
return utftext;
};
let base64encode = function (input) {
var output = '';
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;
input = _utf8_encode(input);
while (i < input.length) {
chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);
enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;
if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}
output =
output +
_keyStr.charAt(enc1) +
_keyStr.charAt(enc2) +
_keyStr.charAt(enc3) +
_keyStr.charAt(enc4);
}
return output;
};
export default {
name: 'sign',
cxt: null,
data() {
return {
// showpage: false,
listeners: [],
ctrl: null,
prevView: '',
lines: [],
line: null,
cid: 'cvs' + getUUID(),
};
},
model: {
prop: 'value',
//这个事件名可以随意写,它实际上是规定了子组件要更新父组件值需要注册的方法
event: 'setSignVal',
},
props: {
edit: {
type: Boolean,
default: false,
},
oldLines: {
default: [],
value: '',
},
},
mounted() {
console.log('labourerSign', this.labourerSign, this.oldLines);
this.initCtrl();
},
methods: {
initCtrl() {
this.show = true;
let cxt = uni.createCanvasContext(this.cid, this);
this.cxt = cxt;
this.ctrl = {
width: 0,
height: 0,
clear: () => {
this.lines = [];
let info = uni
.createSelectorQuery()
.in(this)
.select('.' + this.cid);
info
.boundingClientRect((data) => {
if (data) {
cxt.clearRect(0, 0, data.width, data.height);
if (data.width && data.height) {
this.ctrl.width = data.width;
this.ctrl.height = data.height;
}
}
})
.exec();
this.$emit('setSignVal', this.ctrl.getValue());
this.redraw();
},
getValue: () => {
if (!this.lines.length) return '';
let svg = this._get_svg();
// new Buff
let b64 = base64encode(svg);
let data = 'data:image/svg+xml;base64,' + b64;
return data;
},
};
this.$nextTick(function () {
this.ctrl.clear();
});
},
_get_svg() {
let r = 0;
let paths = [];
let raww = this.ctrl.width;
let rawh = this.ctrl.height;
let width = Math.abs(r) != 90 ? raww : rawh;
let height = Math.abs(r) == 90 ? raww : rawh;
let cx = raww / 2;
let cy = rawh / 2;
let PI = Math.PI;
let R = (r || 0) % 360;
let cosv = Math.cos((R * PI) / 180);
let sinv = Math.sin((R * PI) / 180);
let dcx = (width - raww) / 2;
let dcy = (height - rawh) / 2;
let trans = function (p) {
if (!R) {
return p;
} else {
let nx = (p.x - cx) * cosv - (p.y - cy) * sinv + cx;
let ny = (p.x - cx) * sinv + (p.y - cy) * cosv + cy;
return {
x: nx + dcx,
y: ny + dcy,
};
}
return p;
};
this.lines.map((l) => {
if (l.points.length < 2) {
return;
}
let sp = trans(l.start);
let pts = [`M ${sp.x} ${Number(sp.y)}`];
l.points.map((p) => {
let np = trans(p);
pts.push(`L ${np.x} ${Number(np.y)}`);
});
paths.push(
`<path stroke-linejoin="round" stroke-linecap="round" stroke-width="3" stroke="rgb(0,0,0)" fill="none" d="${pts.join(
' '
)}"/>`
);
});
let svg = `<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="${width}" height="${height}">${paths.join(
'\n'
)}</svg>`;
return svg;
},
clearSignature() {
this.ctrl && this.ctrl.clear();
},
_get_point(e) {
return {
x: e.changedTouches[0].x.toFixed(1),
y: e.changedTouches[0].y.toFixed(1),
};
},
touchstart(e) {
console.log('touchstart');
let p = this._get_point(e);
this.line = {
start: p,
points: [p],
};
this.lines.push(this.line);
},
touchmove(e) {
let p = this._get_point(e);
this.line.points.push(p);
if (!this.tm) {
this.tm = setTimeout(() => {
this.redraw();
this.tm = 0;
}, 10);
}
},
touchend(e) {
let p = this._get_point(e);
this.line.points.push(p);
this.line.end = p;
this.redraw();
this.$emit('setSignVal', this.ctrl.getValue());
// this.$emit('saveLines', this.lines)
this.oldLines.default = this.lines;
this.oldLines.value = this.ctrl.getValue();
},
redraw() {
let cxt = this.cxt;
cxt.setStrokeStyle('#000');
cxt.setLineWidth(3);
var last = null;
this.lines.map((l) => {
cxt.beginPath();
if (l.points.length < 2) {
return;
}
cxt.moveTo(l.start.x, l.start.y);
l.points.map((p) => {
cxt.lineTo(p.x, p.y);
});
cxt.stroke();
});
cxt.draw();
},
},
};
</script>
<style lang="scss" scoped>
$--mainElderFont16: 24rpx;
.edit-con {
height: 100%;
position: relative;
display: flex;
flex-direction: column;
.sign {
padding-bottom: 30rpx;
.content {
margin-bottom: 5px;
display: flex;
align-items: center;
color: #2a8bfc;
text {
font-size: $--mainElderFont16;
color: rgb(52, 158, 251);
margin-right: 6rpx;
}
}
}
.canvas-con {
flex: 1;
overflow-y: scroll;
}
}
.signature-main {
width: 100%;
height: 100%;
display: flex;
flex-flow: column;
}
.signature {
// background: #fff;
background-color: #f1f1f1;
flex: auto;
width: 100%;
height: 100%;
align-self: center;
}
.placeholder {
position: absolute;
font-size: 50rpx;
left: 50%;
top: 50%;
transform: translate(-50%, 0);
font-weight: bold;
color: #b3b5b9;
}
</style>
【uniapp】签名+base64encode
最新推荐文章于 2024-06-03 19:02:39 发布