【uniapp】签名+base64encode

<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>

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值