• 用canvas实现验证码的绘制


    login.vue主文件

      1 <template>
      2     <div class="login-wrapper">
      3         <img src="../../assets/images/logo.png" class="logo" />
      4         <div class="login-box">
      5             <ul class="login-title-list">
      6                 <li class="login-title-item active">账号登录</li>
      7                 <li class="login-title-item">二维码登录</li>
      8             </ul>
      9             <div class="login-body">
     10                 <el-form
     11                     autocomplete="off"
     12                     :model="loginForm"
     13                     :rules="loginRules"
     14                     ref="loginForm"
     15                     label-position="left"
     16                     label-width="0px"
     17                     class="card-box login-form"
     18                 >
     19                     <el-form-item prop="username">
     20                         <svg-icon icon-class="user" class="icon-svg" />
     21                         <el-input placeholder="请输入邮箱" type="text" v-model="loginForm.username" />
     22                     </el-form-item>
     23                     <el-form-item prop="password">
     24                         <svg-icon icon-class="password" class="icon-svg" />
     25                         <el-input placeholder="请输入密码" type="password" v-model="loginForm.password" />
     26                     </el-form-item>
     27                     <el-form-item prop="verifycode" class="form-item-captcha">
     28                         <el-input placeholder="请输入验证码" type="captcha" v-model="loginForm.verifycode" />
     29                         <span @click="refreshCode" class="yzm">
     30                             <s-identify :identifyCode="identifyCode"></s-identify>
     31                         </span>
     32                     </el-form-item>
     33                     <el-form-item class="login-wrap">
     34                         <el-button type="primary" :loading="loading" style="100%;" @click="handleLogin"
     35                             >登录</el-button
     36                         >
     37                     </el-form-item>
     38                 </el-form>
     39                 <div class="login-footer">
     40                     <el-checkbox v-model="rememberPassword">记住密码</el-checkbox>
     41                     <span>忘记密码?</span>
     42                 </div>
     43             </div>
     44         </div>
     45     </div>
     46 </template>
     47 
     48 <script>
     49 import { mapState } from 'vuex';
     50 import SIdentify from './identify.vue';
     51 import { encryptDes } from '../../assets/js/utils/des';
     52 
     53 export default {
     54     name: 'Login',
     55     components: {
     56         SIdentify
     57     },
     58     data() {
     59         // 验证码自定义验证规则
     60         const validateVerifycode = (rule, value, callback) => {
     61             let newVal = value.toLowerCase();
     62             let identifyStr = this.identifyCode.toLowerCase();
     63             if (newVal === '') {
     64                 callback(new Error('请输入验证码'));
     65             } else if (newVal !== identifyStr) {
     66                 callback(new Error('验证码不正确!'));
     67             } else {
     68                 callback();
     69             }
     70         };
     71         return {
     72             loginForm: {
     73                 username: '',
     74                 password: '',
     75                 verifycode: ''
     76             },
     77             identifyCodes: '1234567890ABCDEFGHIGKLMNOPQRSTUVWXYZ',
     78             identifyCode: '',
     79             rememberPassword: true,
     80             loading: false,
     81             loginRules: {
     82                 username: [{ required: true, trigger: 'blur', message: '账号不能为空' }],
     83                 password: [
     84                     { required: true, message: '请输入密码', trigger: 'blur' },
     85                     { min: 6, message: '密码长度最少为6位', trigger: 'blur' }
     86                 ],
     87                 verifycode: [{ required: true, trigger: 'blur', validator: validateVerifycode }]
     88             }
     89         };
     90     },
     91     methods: {
     92         // 生成随机数
     93         randomNum(min, max) {
     94             return Math.floor(Math.random() * (max - min) + min);
     95         },
     96         // 切换验证码
     97         refreshCode() {
     98             this.identifyCode = '';
     99             this.makeCode(this.identifyCodes, 4);
    100         },
    101         // 生成四位随机验证码
    102         makeCode(o, l) {
    103             for (let i = 0; i < l; i++) {
    104                 this.identifyCode += this.identifyCodes[this.randomNum(0, this.identifyCodes.length)];
    105             }
    106         },
    107         handleLogin() {
    108             this.$refs.loginForm.validate(valid => {
    109                 if (valid) {
    110                     this.loading = true;
    111                     const loginParams = {
    112                         loginUserId: this.loginForm.username,
    113                         password: encryptDes(this.loginForm.password)
    114                     };
    115                     this.$store.dispatch('login', loginParams).then(res => {
    116                         this.loading = false;
    117                         if (res.status === 200) {
    118                             this.$store.commit('SET_USER_INFO', res.data.onlineUserInfo);
    119                             this.$router.push({ path: '/' });
    120                         }
    121                     });
    122                 } else {
    123                     return false;
    124                 }
    125             });
    126         }
    127     },
    128     mounted() {
    129         // 验证码初始化
    130         this.identifyCode = '';
    131         this.makeCode(this.identifyCodes, 4);
    132     }
    133 };
    134 </script>

    identify.vue文件

      1 <template>
      2     <div class="s-canvas">
      3         <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
      4     </div>
      5 </template>
      6 <script>
      7 export default {
      8   name: 'SIdentify',
      9   props: {
     10     identifyCode: {
     11       type: String,
     12       default: '1234'
     13     },
     14     fontSizeMin: {
     15       type: Number,
     16       default: 28
     17     },
     18     fontSizeMax: {
     19       type: Number,
     20       default: 40
     21     },
     22     backgroundColorMin: {
     23       type: Number,
     24       default: 180
     25     },
     26     backgroundColorMax: {
     27       type: Number,
     28       default: 240
     29     },
     30     colorMin: {
     31       type: Number,
     32       default: 50
     33     },
     34     colorMax: {
     35       type: Number,
     36       default: 160
     37     },
     38     lineColorMin: {
     39       type: Number,
     40       default: 40
     41     },
     42     lineColorMax: {
     43       type: Number,
     44       default: 180
     45     },
     46     dotColorMin: {
     47       type: Number,
     48       default: 0
     49     },
     50     dotColorMax: {
     51       type: Number,
     52       default: 255
     53     },
     54     contentWidth: {
     55       type: Number,
     56       default: 112
     57     },
     58     contentHeight: {
     59       type: Number,
     60       default: 40
     61     }
     62   },
     63   methods: {
     64     // 生成一个随机数
     65     randomNum(min, max) {
     66       return Math.floor(Math.random() * (max - min) + min);
     67     },
     68     // 生成一个随机的颜色
     69     randomColor(min, max) {
     70       let r = this.randomNum(min, max);
     71       let g = this.randomNum(min, max);
     72       let b = this.randomNum(min, max);
     73       return `rgb(${r},${g},${b})`;
     74     },
     75     drawPic() {
     76       let canvas = document.getElementById('s-canvas');
     77       let ctx = canvas.getContext('2d');
     78       ctx.textBaseline = 'bottom';
     79       // 绘制背景
     80       ctx.fillStyle = this.randomColor(this.backgroundColorMin, this.backgroundColorMax);
     81       ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
     82       // 绘制文字
     83       for (let i = 0; i < this.identifyCode.length; i++) {
     84         this.drawText(ctx, this.identifyCode[i], i);
     85       }
     86       this.drawLine(ctx);
     87       this.drawDot(ctx);
     88     },
     89     drawText(ctx, txt, i) {
     90       ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax);
     91       ctx.font = `${this.randomNum(this.fontSizeMin, this.fontSizeMax)}px SimHei`;
     92       let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
     93       let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
     94       let deg = this.randomNum(-30, 30);
     95       // 修改坐标原点和旋转角度
     96       ctx.translate(x, y);
     97       ctx.rotate((deg * Math.PI) / 270);
     98       ctx.fillText(txt, 0, 0);
     99       // 恢复坐标原点和旋转角度
    100       ctx.rotate((-deg * Math.PI) / 270);
    101       ctx.translate(-x, -y);
    102     },
    103     drawLine(ctx) {
    104       // 绘制干扰线
    105       for (let i = 0; i < 2; i++) {
    106         ctx.strokeStyle = this.randomColor(this.lineColorMin, this.lineColorMax);
    107         ctx.beginPath();
    108         ctx.moveTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight));
    109         ctx.lineTo(this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight));
    110         ctx.stroke();
    111       }
    112     },
    113     drawDot(ctx) {
    114       // 绘制干扰点
    115       for (let i = 0; i < 20; i++) {
    116         ctx.fillStyle = this.randomColor(0, 255);
    117         ctx.beginPath();
    118         ctx.arc(
    119           this.randomNum(0, this.contentWidth),
    120           this.randomNum(0, this.contentHeight),
    121           1,
    122           0,
    123           2 * Math.PI
    124         );
    125         ctx.fill();
    126       }
    127     }
    128   },
    129   watch: {
    130     identifyCode() {
    131       this.drawPic();
    132     }
    133   },
    134   mounted() {
    135     this.drawPic();
    136   }
    137 };
    138 </script>
  • 相关阅读:
    小米范工具系列之二:小米范 web目录扫描器
    小米范工具系列之一:小米范 web查找器
    Layer子域名挖掘机
    unity第一人称
    浏览器的兼容大坑
    java掉系統进程
    java写的服务器,处理多个请求
    java网络练习一
    javaWeb开发原理
    unity传统GUI学习一.
  • 原文地址:https://www.cnblogs.com/guwufeiyang/p/12956229.html
Copyright © 2020-2023  润新知