123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375 |
- <template>
- <view>
- <u-popup :show="show" round="15" mode="center" :closeable="true" :customStyle="{ width: '95%' }" @close="cancelSignature">
- <view class="popup">
- <view class="signature-contain">
- <view class="signature-main">
- <view class="title">请签字</view>
- <canvas disable-scroll="true" class="signature" :class="cid" canvas-id="cvs" @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas>
- <view class="signature-btns">
- <button class="btn" style="background-color: #9e9e9e" @tap="cancelSignature()">取消</button>
- <button class="btn" @tap="onOK()">确定</button>
- </view>
- </view>
- </view>
- </view>
- </u-popup>
- </view>
- </template>
- <script>
- 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 {
- cxt: null,
- data() {
- return {
- ip: this.http.ip,
- VERSION: '1.0.0',
- cid: 'cvs',
- show: false,
- ctrl: null,
- listeners: [],
- prevView: '',
- draws: [],
- lines: [],
- line: null
- };
- },
- props: {
- value: {
- default: ''
- },
- title: {
- type: String,
- default: '请签字'
- },
- disabled: {
- type: Boolean,
- default: false
- }
- },
- watch: {
- value() {
- this.prevView = this.value;
- }
- },
- computed: {
- titles() {
- return this.title.split('');
- },
- absPrevView() {
- var pv = this.prevView;
- // if(pv){
- // pv = this.$wrapUrl(pv)
- // }
- return pv;
- }
- },
- mounted() {
- this.prevView = this.value;
- console.log('dx');
- },
- methods: {
- onOK() {
- uni.showModal({
- title: '提示',
- content: '确定提交签名并签约?',
- success: (res) => {
- if (res.confirm) {
- uni.canvasToTempFilePath(
- {
- canvasId: this.cid,
- fileType: 'png',
- quality: 1, //图片质量
- success: (res) => {
- uni.uploadFile({
- url: this.ip + '/app/common/upload',
- filePath: res.tempFilePath,
- name: 'file',
- header: { Authorization: this.getUser().token },
- success: (res) => {
- let data = JSON.parse(res.data);
- if (data.code == 200) {
- this.$emit('sign', data.fileName);
- this.hideSignature();
- } else {
- uni.showModal({ content: data.msg, showCancel: false });
- }
- uni.hideLoading();
- },
- fail: (res) => {
- uni.hideLoading();
- uni.showModal({ content: '图片上传失败', showCancel: false });
- }
- });
- },
- fail: (err) => {}
- },
- this
- );
- }
- }
- });
- },
- touchSignature() {
- let sig = this.prevView;
- if (!sig || !sig.length) {
- this.showSignature();
- }
- },
- showSignature() {
- if (this.disabled) return;
- if (!this.ctrl) {
- this.initCtrl();
- } else if (!this.show) {
- this.clearSignature();
- this.show = true;
- }
- },
- async getSyncSignature() {
- this.showSignature();
- return await new Promise(async (resolve, reject) => {
- this.listeners.push((res) => {
- resolve(res);
- });
- });
- },
- cancelSignature() {
- this.listeners.map((f) => {
- f(null);
- });
- this.hideSignature();
- },
- hideSignature() {
- this.ctrl && this.ctrl.clear();
- this.show = false;
- },
- clearSignature() {
- this.ctrl && this.ctrl.clear();
- },
- async initCtrl() {
- this.show = true;
- let cxt = uni.createCanvasContext(this.cid, this);
- this.cxt = cxt;
- // cxt.clearRect(0,0,c.width,c.height);
- 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.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;
- // console.log(svg);
- // console.log(data);
- return data;
- }
- };
- this.$nextTick(function () {
- this.ctrl.clear();
- });
- },
- _get_svg() {
- let r = -90;
- 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;
- },
- _get_svg_raw() {
- let paths = [];
- this.lines.map((l) => {
- if (l.points.length < 2) {
- return;
- }
- let pts = [`M ${l.start.x} ${Number(l.start.y)}`];
- l.points.map((p) => {
- pts.push(`L ${p.x} ${Number(p.y)}`);
- });
- paths.push(`<path stroke-linejoin="round" stroke-linecap="round" stroke-width="3" stroke="rgb(0,0,0)" fill="none" d="${pts.join(' ')}"/>`);
- });
- let width = this.ctrl.width;
- let height = this.ctrl.height;
- 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}" transform="rotate(-90)">${paths.join(
- '\n'
- )}</svg>`;
- return svg;
- },
- _get_point(e) {
- return {
- x: e.changedTouches[0].x.toFixed(1),
- y: e.changedTouches[0].y.toFixed(1)
- };
- },
- touchstart(e) {
- 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();
- },
- 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();
- },
- canvasIdErrorCallback: function (e) {
- console.error(e.detail.errMsg);
- }
- }
- };
- </script>
- <style lang="scss">
- .popup {
- padding: 15px;
- background-color: white;
- border-radius: 10px;
- .signature-contain {
- width: 100%;
- .signature-main {
- .title {
- text-align: center;
- }
- .signature {
- width: 100%;
- border: 1px dotted black;
- border-bottom: 1px dotted black;
- margin: 10px 0;
- }
- .btn {
- margin-top: 10px;
- }
- }
- }
- }
- </style>
|