index.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /**
  2. * 获取范围内的随机数
  3. * @param {Number} min 最小值
  4. * @param {Number} max 最大值
  5. */
  6. const randomNum = (min, max) => {
  7. return Math.floor(Math.random() * (max - min) + min)
  8. }
  9. /**
  10. * 获取范围内的随机颜色值
  11. * @param {Number} min 最小值
  12. * @param {Number} max 最大值
  13. */
  14. const randomColor = (min, max) => {
  15. const _r = randomNum(min, max)
  16. const _g = randomNum(min, max)
  17. const _b = randomNum(min, max)
  18. return `rgb(${_r}, ${_g}, ${_b})`
  19. }
  20. /**
  21. * 创建 canvas 绘图上下文
  22. * @param {Object} ctx canvas 绘图上下文
  23. * @param {Object} opts 配置项
  24. * @param {String} opts.str 验证码范围
  25. * @param {Number} opts.num 验证码长度,默认值 6
  26. * @param {Number} opts.width 画布宽度,默认值 120
  27. * @param {Number} opts.height 画布高度,默认值 40
  28. * @param {String} opts.bgColor 画布背景色
  29. * @param {String} opts.fontColor 画布字体颜色
  30. * @param {Boolean} opts.hasPoint 是否显示干扰点,默认 true
  31. * @param {Boolean} opts.hasLine 是否显示干扰线,默认 true
  32. */
  33. const render = (ctx, opts = {}) => {
  34. const { str, num, width, height, bgColor, fontColor, hasPoint, hasLine } = opts
  35. let vcode = ''
  36. if (typeof ctx.setTextBaseline === 'function') {
  37. ctx.setTextBaseline('bottom')
  38. }
  39. // 绘制矩形,并设置填充色
  40. ctx.setFillStyle(bgColor ? bgColor : randomColor(180, 240))
  41. ctx.fillRect(0, 0, width, height)
  42. // 绘制随机生成 n 位的验证码
  43. for (let i = 0; i < num; i++) {
  44. const x = (width - 10) / num * i + 10
  45. const y = randomNum(height / 2, height)
  46. const deg = randomNum(-45, 45)
  47. const txt = str[randomNum(0, str.length)]
  48. const fontSize = randomNum(16, 40)
  49. const halfHeight = parseInt(height / 2)
  50. vcode += txt
  51. ctx.setFillStyle(fontColor ? fontColor : randomColor(10, 100))
  52. ctx.setFontSize(fontSize > halfHeight ? halfHeight : fontSize)
  53. ctx.translate(x, y)
  54. ctx.rotate(deg * Math.PI / 180)
  55. ctx.fillText(txt, 0, 0)
  56. ctx.rotate(-deg * Math.PI / 180)
  57. ctx.translate(-x, -y)
  58. }
  59. // 绘制干扰线
  60. if (!!hasLine) {
  61. for (let i = 0; i < num; i++) {
  62. ctx.setStrokeStyle(randomColor(90, 180))
  63. ctx.beginPath()
  64. ctx.moveTo(randomNum(0, width), randomNum(0, height))
  65. ctx.lineTo(randomNum(0, width), randomNum(0, height))
  66. ctx.stroke()
  67. }
  68. }
  69. // 绘制干扰点
  70. if (!!hasPoint) {
  71. for (let i = 0; i < num * 10; i++) {
  72. ctx.setFillStyle(randomColor(0, 255))
  73. ctx.beginPath()
  74. ctx.arc(randomNum(0, width), randomNum(0, height), 1, 0, 2 * Math.PI)
  75. ctx.fill()
  76. }
  77. }
  78. return vcode
  79. }
  80. Component({
  81. properties: {
  82. str: {
  83. type: String,
  84. value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789',
  85. },
  86. num: {
  87. type: Number,
  88. value: 6,
  89. },
  90. width: {
  91. type: Number,
  92. value: 120,
  93. },
  94. height: {
  95. type: Number,
  96. value: 40,
  97. },
  98. bgColor: {
  99. type: String,
  100. value: '',
  101. },
  102. fontColor: {
  103. type: String,
  104. value: '',
  105. },
  106. hasPoint: {
  107. type: Boolean,
  108. value: true,
  109. },
  110. hasLine: {
  111. type: Boolean,
  112. value: true,
  113. },
  114. canvasId: {
  115. type: String,
  116. value: 'wux-vcode',
  117. },
  118. },
  119. methods: {
  120. /**
  121. * 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中
  122. */
  123. draw() {
  124. const { width, height, canvasId } = this.data
  125. this.ctx = this.ctx || wx.createCanvasContext(canvasId, this)
  126. this.ctx.clearRect(0, 0, width, height)
  127. const value = render(this.ctx, this.data)
  128. this.ctx.draw(false, () => this.triggerEvent('change', { value }))
  129. },
  130. },
  131. attached() {
  132. this.draw()
  133. },
  134. detached() {
  135. this.ctx = null
  136. },
  137. })