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>

注:参考其他博主改动的

posted @ 2021-05-07 17:01  老龟  阅读(422)  评论(0)    收藏  举报