vue组件生成随机验证码
实现效果如下
点击会刷新随机生成指定位数的验证码
Math.floor 是对一个数字向下取整
charAt方法可返回指定位置的字符
toLowerCase() 把大写字母转换为小写字母
参数 | 说明 | 类型 | 默认值 |
identifyCode
|
需要展示的验证码 | string | 无 |
fontSizeMin
|
最小字体 | number | 16 |
fontSizeMax
|
最大字体 | number | 40 |
backgroundColorMin
|
背景颜色色差最小值,最小0 | 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 | 78 |
contentHeight
|
画布高度 | number | 34 |
代码
1 <template> 2 <div class="popup"> 3 <div class="off" @click="off()"></div> 4 <div class="content"> 5 <section> 6 <input type="text" v-model="pictureCaptcha" placeholder="请输入图中验证码"> 7 <div class="s-canvas box" ref="canvas" @click="createdCode"> 8 <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas> 9 </div> 10 </section> 11 <p @click="createdCode">点击图形刷新</p> 12 <div class="comfirm" @click="comfirm()">确定</div> 13 </div> 14 </div> 15 </template> 16 <script> 17 import Vue from 'vue' 18 import { Toast } from 'vant' 19 export default Vue.extend({ 20 props: { 21 fontSizeMin: { 22 type: Number, 23 default: 25 24 }, 25 fontSizeMax: { 26 type: Number, 27 default: 30 28 }, 29 backgroundColorMin: { 30 type: Number, 31 default: 255 32 }, 33 backgroundColorMax: { 34 type: Number, 35 default: 255 36 }, 37 colorMin: { 38 type: Number, 39 default: 0 40 }, 41 colorMax: { 42 type: Number, 43 default: 160 44 }, 45 lineColorMin: { 46 type: Number, 47 default: 100 48 }, 49 lineColorMax: { 50 type: Number, 51 default: 255 52 }, 53 dotColorMin: { 54 type: Number, 55 default: 0 56 }, 57 dotColorMax: { 58 type: Number, 59 default: 255 60 }, 61 contentWidth: { 62 type: Number, 63 default: 78 64 }, 65 contentHeight: { 66 type: Number, 67 default: 34 68 } 69 }, 70 data () { 71 return { 72 identifyCode: '', 73 pictureCaptcha: '' 74 } 75 }, 76 mounted () { 77 this.$store.commit('setShowTab', false) 78 this.createdCode() 79 }, 80 methods: { 81 // 生成4个随机数 82 createdCode () { 83 const len = 4 // 这里控制验证码为4个随机数 84 const codeList = [] 85 const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' 86 const charsLen = chars.length 87 for (let i = 0; i < len; i++) { 88 codeList.push(chars.charAt(Math.floor(Math.random() * charsLen))) 89 } 90 this.identifyCode = codeList.join('') 91 // this.$emit('getIdentifyCode', this.identifyCode.toLowerCase()) 92 this.drawPic() 93 }, 94 95 // 生成一个随机数 96 randomNum (min, max) { 97 return Math.floor(Math.random() * (max - min) + min) 98 }, 99 // 生成一个随机的颜色 100 randomColor (min, max) { 101 const r = this.randomNum(min, max) 102 const g = this.randomNum(min, max) 103 const b = this.randomNum(min, max) 104 return 'rgb(' + r + ',' + g + ',' + b + ')' 105 }, 106 107 drawPic () { 108 // 获取dom元素 109 const canvas = document.getElementById('s-canvas') 110 // 配置绘画环境 111 const ctx = canvas.getContext('2d') 112 // 在文字下方绘制一条线 113 ctx.textBaseline = 'bottom' 114 // 绘制背景 115 ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax) 116 ctx.fillRect(0, 0, this.contentWidth, this.contentHeight) 117 // 绘制文字 118 for (let i = 0; i < this.identifyCode.length; i++) { 119 this.drawText(ctx, this.identifyCode[i], i) 120 } 121 console.log(this.identifyCode) 122 this.drawLine(ctx) 123 // this.drawDot(ctx) 124 }, 125 126 drawText (ctx, txt, i) { 127 ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax) 128 ctx.font = this.randomNum(this.fontSizeMin, this.fontSizeMax) + 'px SimHei' 129 const x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1)) 130 const y = this.randomNum(this.fontSizeMax, this.contentHeight - 5) 131 var deg = this.randomNum(-45, 45) 132 // 修改坐标原点和旋转角度 133 ctx.translate(x, y) 134 ctx.rotate(deg * Math.PI / 180) 135 ctx.fillText(txt, 0, 0) 136 // 恢复坐标原点和旋转角度 137 ctx.rotate(-deg * Math.PI / 180) 138 ctx.translate(-x, -y) 139 }, 140 141 // 绘制干扰线 142 drawLine (ctx) { 143 for (let i = 0; i < 5; i++) { 144 ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax) 145 ctx.beginPath() 146 ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) 147 ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight)) 148 ctx.stroke() 149 } 150 }, 151 // 图片验证码校验 152 comfirm () { 153 if (this.pictureCaptcha !== '') { 154 // 判断验证码是否正确 155 if (this.identifyCode.toLowerCase() === this.pictureCaptcha.toLowerCase()) { 156 console.log('发送短信验证码/验证成功') 157 // 验证成功执行的代码158 return 159 } 160 } 161 Toast({ 162 message: '验证码错误,请重新输入', 163 position: 'top', 164 duration: 1000 165 }) 166 this.pictureCaptcha = '' 167 this.createdCode() 168 } 169 // 绘制干扰点 170 drawDot (ctx) { 171 for (let i = 0; i < 80; i++) { 172 ctx.fillStyle = this.randomColor(0, 255) 173 ctx.beginPath() 174 ctx.arc(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, 2 * Math.PI) 175 ctx.fill() 176 } 177 } 178 } 179 }) 180 </script> 181 <style scoped lang="scss"> 182 .s-canvas { 183 height: 38px; 184 width: 80px; 185 padding: 0; 186 margin: 0; 187 cursor: pointer; 188 } 189 // 验证码弹出框 190 .popup{ 191 position: fixed; 192 top: 0; 193 width: 100%; 194 height: 100%; 195 background: rgba(1, 1, 1, 0.6); 196 } 197 .off{ 198 position: absolute; 199 right: 2.375rem; 200 top: 4.25rem; 201 width: 34px; 202 height: 34px; 203 background: url('../images/common/pic_tc.png') no-repeat; 204 background-size: 100%; 205 } 206 .content{ 207 width: 18.75rem; 208 height: 11.5625rem; 209 margin: 13.5625rem auto; 210 background: #fff; 211 border-radius: 10px; 212 overflow: hidden; 213 section{ 214 width: 15.625rem; 215 height: 2.6875rem; 216 margin: 3.125rem auto 0; 217 border-bottom: 1px solid #eceeef; 218 input{ 219 width: 9.375rem; 220 margin-right: 1.25rem; 221 caret-color: #44b549; 222 } 223 .box{ 224 display: inline-block; 225 top: 0.1875rem; 226 border: 1px solid #e9c581; 227 } 228 } 229 p{ 230 width: 15.625rem; 231 margin: 0 auto 2.25rem; 232 text-align: right; 233 } 234 .comfirm{ 235 text-align: center; 236 color: #44b549; 237 } 238 } 239 </style>
注:参考其他博主改动的