登录实现图片验证码

2020/5/21 vuehtml

# 登录实现图片验证码

# 背景

登录基本是很多前端网站都需要的功能了吧,验证码防止“注册机”也是比较常见的了。这里用vue来实实现下登录的图片验证码功能,当然普通的H5项目也是可以实现,原理是相通的。

# Vue实现图片验证码

# 封装自定义的图片验证码组件IdentifyCode

API参考

在这里插入图片描述

代码

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

# 使用IdentifyCode组件生成验证码

<template>
	<!--    图片验证码    -->
	<div @click="refreshCode">
	     <identify-code
	         :identifyCode="identifyCode"
	         :contentWidth="150"
	         :contentHeight="50"
	         :fontSizeMin="50"
	     />
	</div>
</template>
<script>
    import IdentifyCode from '../components/IdentifyCode'

    export default {
        name: 'login',
        components: {
            'identify-code': IdentifyCode,
        },
        data: () => ({
        	//生成验证码的字符范围
            identifyCodes: "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz0123456789",
            //生成的验证码
            identifyCode: "",
        }),
        methods: {
            //生成随机数
            randomNum(min, max) {
                return Math.floor(Math.random() * (max - min) + min);
            },
            //刷新验证码
            refreshCode() {
                this.identifyCode = "";
                this.makeCode(this.identifyCodes, 4);
            },
            //生成验证码,l为生成验证码的长度
            makeCode(o, l) {
                for (let i = 0; i < l; i++) {
                	//随机字符串拼接
                    this.identifyCode += this.identifyCodes[
                        this.randomNum(0, this.identifyCodes.length)
                    ];
                }
            }
        },
        mounted() {
            this.identifyCode = "";
            this.makeCode(this.identifyCodes, 4);
        },
    };
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# 效果图

在这里插入图片描述

如果需要验证码的规则验证,想要简单验证,请参看我的另一篇博客: Vuetify利用表单验证规则,简化表单验证及错误信息提示的实现 (opens new window)

# 普通H5项目图片验证码生成

可直接参看上文的methods中的方法自行封装。