最近项目中要用到图片验证码,网上一查有很多,基本都是千篇一律的4位纯数字验证码。首先得感谢那位一代目兄台提供的模板,由于不能满足需求,所以对其进行了改造升级。

经改造的图片验证码能满足一下情形使用:①、验证码位数;②、纯数字和纯字母的验证码;③、数字和字母混合的验证码;④、字母的大小写;⑤、数字和字母(大小写)混合下各自的位数;⑥、随机生成混合情况下各自的位数;⑦、验证码随机排序。大致就这些组合吧,基本的需求都能满足,话不多说,看~

1、先把一代目兄台的canvas参数搬一下

参数 说明 类型 默认值
identifyCode 展示的图片验证码 string 1234
fontSizeMin 字体大小,最小值 number 16
fontSizeMax 字体大小,最大值 number 40
backgroundColorMin 背景颜色色值最小值,最小为 number 180
backgroundColorMax 背景颜色色值最大值,最大为255 number 240
colorMin 字体颜色色值最小值,最小为0 number 50
colorMax 字体颜色色值最大值,最大为255 number 160
lineColorMin 干扰线颜色色值最小值,最小为0 number 40
lineColorMax 干扰线颜色色值最大值,最大为255 number 180
dotColorMin 干扰点颜色色值最小值,最小为0 number 0
dotColorMax 干扰点颜色色值最大值,最大为255 number 255
contentWidth 画布宽度 number 160
contentHeight 画布高度 number 40

2、主角儿identify.vue组件登场

  1. <template>
  2. <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
  3. </template>
  4. <script>
  5. export default {
  6. name: 'SIdentify',
  7. props: {
  8. // 图片验证码
  9. identifyCode: {
  10. type: String,
  11. default: '1234'
  12. },
  13. // 字体最小值
  14. fontSizeMin: {
  15. type: Number,
  16. default: 28
  17. },
  18. // 字体最大值
  19. fontSizeMax: {
  20. type: Number,
  21. default: 34
  22. },
  23. // 背景颜色色值最小值,最小为0
  24. backgroundColorMin: {
  25. type: Number,
  26. default: 200
  27. },
  28. // 背景颜色色值最大值,最大为255
  29. backgroundColorMax: {
  30. type: Number,
  31. default: 240
  32. },
  33. // 字体颜色色值最小值,最小为0
  34. colorMin: {
  35. type: Number,
  36. default: 0
  37. },
  38. // 字体颜色色值最大值,最大为255
  39. colorMax: {
  40. type: Number,
  41. default: 180
  42. },
  43. // 干扰线颜色色值最小值,最小为0
  44. lineColorMin: {
  45. type: Number,
  46. default: 150
  47. },
  48. // 干扰线颜色色值最大值,最大为255
  49. lineColorMax: {
  50. type: Number,
  51. default: 200
  52. },
  53. // 干扰点颜色色值最小值,最小为0
  54. dotColorMin: {
  55. type: Number,
  56. default: 100
  57. },
  58. // 干扰点颜色色值最大值,最大为255
  59. dotColorMax: {
  60. type: Number,
  61. default: 250
  62. },
  63. // 画布宽度
  64. contentWidth: {
  65. type: Number,
  66. default: 100
  67. },
  68. // 画布高度
  69. contentHeight: {
  70. type: Number,
  71. default: 40
  72. }
  73. },
  74. mounted () {
  75. this.drawPic()
  76. },
  77. methods: {
  78. /**
  79. * 生成一个随机数
  80. * @param {number} min 随机数最小值
  81. * @param {number} max 随机数最大值
  82. */
  83. randomNum (min, max) {
  84. return Math.floor(Math.random() * (max - min) + min)
  85. },
  86. /**
  87. * 生成一个随机的颜色
  88. * @param {number} min 随机数最小值
  89. * @param {number} max 随机数最大值
  90. */
  91. randomColor (min, max) {
  92. const r = this.randomNum(min, max)
  93. const g = this.randomNum(min, max)
  94. const b = this.randomNum(min, max)
  95. return 'rgb(' + r + ',' + g + ',' + b + ')'
  96. },
  97. /**
  98. * 绘制图片验证码
  99. */
  100. drawPic () {
  101. let canvas = document.querySelector('#s-canvas')
  102. let ctx = canvas.getContext('2d')
  103. ctx.textBaseline = 'bottom'
  104. // 绘制背景
  105. ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax)
  106. ctx.fillRect(0, 0, this.contentWidth, this.contentHeight)
  107. // 绘制干扰点
  108. this.drawDot(ctx)
  109. // 绘制验证码
  110. for (let i = 0; i < this.identifyCode.length; i++) {
  111. this.drawText(ctx, this.identifyCode[i], i)
  112. }
  113. // 绘制干扰线
  114. this.drawLine(ctx)
  115. },
  116. /**
  117. * 绘制文本单个验证码
  118. * @param {object} ctx canvas上下文对象
  119. * @param {string} txt 单个验证码
  120. * @param {number} i 单个验证码序号
  121. */
  122. drawText (ctx, txt, i) {
  123. ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax)
  124. ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei'
  125. let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1))
  126. let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5)
  127. let deg = this.randomNum(-45, 45)
  128. // 修改坐标原点和旋转角度
  129. ctx.translate(x, y)
  130. ctx.rotate(deg * Math.PI / 180)
  131. ctx.fillText(txt, 0, 0)
  132. // 恢复坐标原点和旋转角度
  133. ctx.rotate(-deg * Math.PI / 180)
  134. ctx.translate(-x, -y)
  135. },
  136. /**
  137. * 绘制干扰线
  138. * @param {object} ctx canvas上下文对象
  139. */
  140. drawLine (ctx) {
  141. for (let i = 0; i < 8; i++) {
  142. ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax)
  143. ctx.beginPath()
  144. ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
  145. ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight))
  146. ctx.stroke()
  147. }
  148. },
  149. /**
  150. * 绘制干扰点
  151. * @param {object} ctx canvas上下文对象
  152. */
  153. drawDot (ctx) {
  154. for (let i = 0; i < 60; i++) {
  155. ctx.fillStyle = this.randomColor(0, 255)
  156. ctx.beginPath()
  157. ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI)
  158. ctx.fill()
  159. }
  160. }
  161. },
  162. watch: {
  163. identifyCode () {
  164. this.drawPic()
  165. }
  166. }
  167. }
  168. </script>

3、对图片验证码组件的引用

为了方便演示,直接在App.vue页面中引用

  1. <template>
  2. <div id="app" @click="refreshCode">
  3. <s-identify :identifyCode="identifyCode"></s-identify>
  4. </div>
  5. </template>
  6. <script>
  7. import SIdentify from './components/identify'
  8. export default {
  9. name: 'App',
  10. data () {
  11. return {
  12. makeCode: '',
  13. identifyCode: ''
  14. }
  15. },
  16. mounted () {
  17. this.makeIdentifyCode({ randomTypeLen: true })
  18. },
  19. methods: {
  20. /**
  21. * 随机生成一个0~9之间的数
  22. */
  23. randomNum () {
  24. return Math.floor(Math.random() * 10)
  25. },
  26. /**
  27. * 随机生成一个字母
  28. * @param {boolean} isUupper 生成大写字母
  29. */
  30. randomAlphabet ({ isUupper = false } = {}) {
  31. // a的Unicode值为97,z的Unicode值为123
  32. const alphabet = String.fromCharCode(Math.floor(Math.random() * 25) + 97)
  33. if (!isUupper) {
  34. return alphabet
  35. } else {
  36. return alphabet.toUpperCase()
  37. }
  38. },
  39. /**
  40. * 生成图片验证码
  41. * @param {number} length 图片验证码位数
  42. * @param {boolean} typeMix 数字和字母混合
  43. * @param {string} pureNumber 纯数字('number')或者字母('alphabet')
  44. * @param {boolean} randomTypeLen 随机生成类型个数组合
  45. * @param {boolean} capsLookMix 字母大小写混合
  46. * @param {number} numLength 混合类型下的数字个数
  47. * @param {number} uupperLength 大写字母的个数
  48. */
  49. makeIdentifyCode ({ length = 4, typeMix = true, pureNumber = 'alphabet', randomTypeLen = false, capsLookMix = false, numLength = 2, uupperLength = 1 } = {}) {
  50. this.makeCode = ''
  51. // 数字和字母混合
  52. if (typeMix) {
  53. // 随机生成类型个数组合
  54. if (randomTypeLen) {
  55. // 字母大小写混合
  56. if (capsLookMix) {
  57. const numLength = Math.floor(Math.random() * length) + 1
  58. const uupperLength = numLength === length ? 0 : Math.floor(Math.random() * (length - numLength)) + 1
  59. for (let i = 0; i < numLength; i++) {
  60. this.makeCode += this.randomNum()
  61. }
  62. for (let i = 0; i < uupperLength; i++) {
  63. this.makeCode += this.randomAlphabet({ isUupper: true })
  64. }
  65. if (numLength + uupperLength < length) {
  66. for (let i = 0; i < length - numLength - uupperLength; i++) {
  67. this.makeCode += this.randomAlphabet()
  68. }
  69. }
  70. } else {
  71. const numLength = Math.floor(Math.random() * length) + 1
  72. for (let i = 0; i < numLength; i++) {
  73. this.makeCode += this.randomNum()
  74. }
  75. if (numLength < length) {
  76. for (let i = 0; i < length - numLength; i++) {
  77. this.makeCode += this.randomAlphabet()
  78. }
  79. }
  80. }
  81. } else {
  82. // 字母大小写混合
  83. if (capsLookMix) {
  84. const tempNumLength = numLength < 0 ? 2 : numLength > length ? 2 : numLength
  85. const tempUupperLength = uupperLength < 0 ? 1 : uupperLength > length - tempNumLength ? 1 : uupperLength
  86. for (let i = 0; i < tempNumLength; i++) {
  87. this.makeCode += this.randomNum()
  88. }
  89. for (let i = 0; i < tempUupperLength; i++) {
  90. this.makeCode += this.randomAlphabet({ isUupper: true })
  91. }
  92. if (tempNumLength + tempUupperLength < length) {
  93. for (let i = 0; i < length - tempNumLength - tempUupperLength; i++) {
  94. this.makeCode += this.randomAlphabet()
  95. }
  96. }
  97. } else {
  98. const tempNumLength = numLength < 0 ? 2 : numLength > length ? 2 : numLength
  99. for (let i = 0; i < tempNumLength; i++) {
  100. this.makeCode += this.randomNum()
  101. }
  102. if (tempNumLength < length) {
  103. for (let i = 0; i < length - tempNumLength; i++) {
  104. this.makeCode += this.randomAlphabet()
  105. }
  106. }
  107. }
  108. }
  109. } else {
  110. // 纯数字('number')
  111. if (pureNumber === 'number') {
  112. for (let i = 0; i < length; i++) {
  113. this.makeCode += this.randomNum()
  114. }
  115. }
  116. // 纯字母('alphabet')
  117. if (pureNumber === 'alphabet') {
  118. // 字母大小写混合
  119. if (capsLookMix) {
  120. const tempUupperLength = uupperLength < 0 ? 1 : uupperLength > length ? 1 : uupperLength
  121. for (let i = 0; i < tempUupperLength; i++) {
  122. this.makeCode += this.randomAlphabet({ isUupper: true })
  123. }
  124. if (tempUupperLength < length) {
  125. for (let i = 0; i < length - tempUupperLength; i++) {
  126. this.makeCode += this.randomAlphabet()
  127. }
  128. }
  129. } else {
  130. for (let i = 0; i < length; i++) {
  131. this.makeCode += this.randomAlphabet()
  132. }
  133. }
  134. }
  135. }
  136. this.shuffle(this.makeCode)
  137. },
  138. /**
  139. * 图片验证码随机排序
  140. * @param {string} str 图片验证码
  141. */
  142. shuffle (str) {
  143. this.identifyCode = [...str].sort(() => Math.random() - 0.5).join('')
  144. console.log(this.identifyCode)
  145. },
  146. /**
  147. * 更换图片验证码
  148. */
  149. refreshCode () {
  150. this.makeIdentifyCode({ randomTypeLen: true })
  151. }
  152. },
  153. components: {
  154. 's-identify': SIdentify
  155. }
  156. }
  157. </script>

就这样吧,完事儿~

Vue图片验证码-自定义组件高级版的更多相关文章

  1. vue.js2.0 自定义组件初体验

    理解 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能.在有些情况 ...

  2. vue图片上传组件

    前言:很多项目中都需要用到图片上传功能,而其多处使用的要求,为了避免重复造轮子,让我决定花费一些时间去深入了解,最终封装了一个vue的图片上传组件.现将总结再次,希望有帮助. Layout <d ...

  3. VUE 图片验证码

    1. 概述 1.1 说明 在开发过程中,有时候需要使用图片验证码进行增加安全强度,在点击图片时更新新的图片验证码,记录此功能,以便后期使用. 2. 示例 2.1 vue示例代码 <templat ...

  4. Vue.extend提供自定义组件的构造器

    Vue.extend 返回的是一个“扩展实例构造器”,也就是预设了部分选项的Vue实例构造器.经常服务于Vue.component用来生成组件,可以简单理解为当在模板中遇到该组件名称作为标签的自定义元 ...

  5. vue框架之自定义组件中使用v-model

    通常 vue在html常见表单空间支持v-model双向绑定例如 <input v-model="message" placeholder="edit me&quo ...

  6. vue怎么给自定义组件绑定原生事件

     下面主要以4个示例Demo演示(示例代码JS引用的Vue CDN),建议小伙伴直接复制示例代码运行查看, 赶时间的小伙伴可直接往下拉,看示例demo4 注:全局或局部注册的组件称为子组件,其中声明的 ...

  7. vue之全局自定义组件

    在项目开发中,往往需要使用到一些公共组件,比如,弹出消息.面包屑或者其它的组件,为了使用方便,将其以插件的形式融入到vue中,以面包屑插件为例: 1.创建公共组件MyBread.vue <tem ...

  8. Vue 获取验证码倒计时组件

    子组件 <template> <a class="getvalidate":class="{gray: (!stop)}"@click='cl ...

  9. Vue第一个自定义组件:数字输入框(number-input)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. 70. Climbing Stairs QuestionEditorial Solution

    You are climbing a stair case. It takes n steps to reach to the top. Each time you can either climb ...

  2. xgboost load model from demp text file

    python package : https://github.com/mwburke/xgboost-python-deploy import xgboost as xgb import numpy ...

  3. python之sorted用法

    operator.itemgetter函数 operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),下面看例子. a = [1, ...

  4. GO语言slice详解(结合源码)

    一.GO语言中slice的定义 slice 是一种结构体类型,在源码中的定义为: src/runtime/slice.go type slice struct { array unsafe.Point ...

  5. 推荐算法之因子分解机(FM)

    在这篇文章我们将介绍因式分解机模型(FM),为行文方便后文均以FM表示.FM模型结合了支持向量机与因子分解模型的优点,并且能够用了回归.二分类以及排序任务,速度快,是推荐算法中召回与排序的利器.FM算 ...

  6. 使用 pyenv 管理不同的 Python 版本

    1. pyenv 的安装 $ yum install git -y $ yum install gcc make patch gdbm-devel openssl-devel sqlite-devel ...

  7. Windwos日志分析

    Windows日志分析工具 查看系统日志方法: 在“开始”菜单上,依次指向“所有程序”.“管理工具”,然后单击“事件查看器” 按 "Window+R",输入 ”eventvwr.m ...

  8. WinBox软路由的自定义IP设定

             软路由ros(MIKRTIK)安装简单步骤 由于本主也是刚刚接触软路由这个硬件方面的知识.所以也是略知皮毛而已,今天通过网上的学习,然后自己总结了一下怎么在软路由中设定一个自定义IP ...

  9. c++ bool

    bool 就两个值,真或者假,通常用来存储关系表达式或者逻辑表达式的结果. 以前是用 int 来表示真假,大 int 有多个值,所以才规定 0 为假,非零为真,导致对应关系比较麻烦,有了 bool 就 ...

  10. 解决掉你心中 js function与Function的关系的疑问

    前言 在网上有很多关于js function 与 Function直接关系的文章. 但是我感觉过于抽象化了,那么如何是具体化的解释? 正文部分为个人理解部分,如有不对望指出. 正文 <scrip ...