<template>
  <div style="padding: 1px 2px; cursor: pointer;" @click="refreshCode">
    <canvas id="s-canvas" :width="cavWidth" :height="cavHeight" />
  </div>
</template>

<script>
export default {
  name: 'GraphicVerify',
  props: {
    verifyCode: {
      //默认***
      type: String,
      default: '1234',
    },
    verifyLength: {
      // 验证码位数
      type: Number,
      default: 4,
    },
    refreshTime: {
      //验证码最后刷新时间
      type: Number,
      default: 0,
    },
    fontSizeMin: {
      // 字体最小值
      type: Number,
      default: 25,
    },
    fontSizeMax: {
      // 字体最大值
      type: Number,
      default: 35,
    },
    bgColorMin: {
      // 验证码图片背景色最小值
      type: Number,
      default: 200,
    },
    bgColorMax: {
      // 验证码图片背景色最大值
      type: Number,
      default: 220,
    },
    dotColorMin: {
      // 干扰点颜色最小值
      type: Number,
      default: 60,
    },
    dotColorMax: {
      // 干扰点颜色最大值
      type: Number,
      default: 128,
    },
    dotCount: {
      // 干扰点个数
      type: Number,
      default: 30,
    },
    cavWidth: {
      // 绘制宽度
      type: Number,
      default: 116,
    },
    cavHeight: {
      // 绘制高度
      type: Number,
      default: 40,
    },
  },
  data() {
    return {
      chars: [
        '0',
        '1',
        '2',
        '3',
        '4',
        '5',
        '6',
        '7',
        '8',
        '9',
        'a',
        'b',
        'c',
        'd',
        'e',
        'f',
        'g',
        'h',
        'j',
        'k',
        'm',
        'n',
        'p',
        'q',
        'r',
        's',
        't',
        'u',
        'v',
        'w',
        'x',
        'y',
        'z',
      ],
    }
  },
  mounted() {
    this.refreshCode()
  },
  methods: {
    // 生成随机数
    randNum(min, max) {
      return Math.floor(Math.random() * (max - min) + min)
    },
    // 生成随机颜色
    randomColor(min, max) {
      return (
        'rgb(' +
        this.randNum(min, max) +
        ',' +
        this.randNum(min, max) +
        ',' +
        this.randNum(min, max) +
        ')'
      )
    },
    drawPic(content) {
      let canvas = document.getElementById('s-canvas')
      let ctx = canvas.getContext('2d')
      ctx.textBaseline = 'bottom'
      // 绘制背景
      ctx.fillStyle = this.randomColor(this.bgColorMin, this.bgColorMax)
      ctx.fillRect(0, 0, this.cavWidth, this.cavHeight)
      // 绘制文字
      for (let i = 0; i < content.length; i++) {
        this.drawText(
          ctx,
          content[i],
          ((i + 1) * this.cavWidth) / (content.length + 1),
          this.randNum(this.fontSizeMax, this.cavHeight - 5)
        )
      }
      this.drawLine(ctx)
      this.drawDot(ctx)
    },
    drawText(ctx, txt, x, y) {
      ctx.fillStyle = this.randomColor(50, 160)
      ctx.font = this.randNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
      var deg = this.randNum(-30, 30)
      // 修改坐标原点和旋转角度
      ctx.translate(x, y)
      ctx.rotate((deg * Math.PI) / 180)
      ctx.fillText(txt, 0, 0)
      // 恢复坐标原点和旋转角度
      ctx.rotate((-deg * Math.PI) / 180)
      ctx.translate(-x, -y)
    },
    drawLine(ctx) {
      // 绘制干扰线
      for (let i = 0; i < 5; i++) {
        ctx.strokeStyle = this.randomColor(100, 200)
        ctx.beginPath()
        ctx.moveTo(this.randNum(0, this.cavWidth), this.randNum(0, this.cavHeight))
        ctx.lineTo(this.randNum(0, this.cavWidth), this.randNum(0, this.cavHeight))
        ctx.stroke()
      }
    },
    drawDot(ctx) {
      // 绘制干扰点
      for (let i = 0; i < this.dotCount; i++) {
        ctx.fillStyle = this.randomColor(0, 255)
        ctx.beginPath()
        ctx.arc(this.randNum(0, this.cavWidth), this.randNum(0, this.cavHeight), 1, 0, 2 * Math.PI)
        ctx.fill()
      }
    },
    //刷新验证码
    refreshCode() {
      let code = ''
      for (let i = 0; i < this.verifyLength; i++) {
        code += this.chars[this.randNum(i % 2 != 0 ? 0 : 10, i % 2 != 0 ? 10 : this.chars.length)]
      }

      this.drawPic(code)

      // this.verifyCode = code
      this.$emit('update:verifyCode', code)
      this.$emit('update:refreshTime', new Date().getTime())
    },
  },
  watch: {
    verifyCode(curVal, oldVal) {
      if (curVal && curVal != '') {
        this.drawPic(curVal)
      }
    },
  },
}
</script>
<style scoped>
.cav-contanier {
  padding: 1px 2px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}
</style>
