一、前言
当我们在平时进行登录或者注册账号的时候,往往都会遇到验证动态验证码的情况,当然现在更流行的是一些滑动拼图或者是文字点选,下面我将介绍以下我实现动态验证码的思路。
二、Canvas简介
- 什么是Canvas?
HTML5新增的元素,通过使用脚本语言(JS)来在特定的区域绘制图形,可以制作照片集和简单的动画,也可以处理和渲染视频。
- Canvas的基本使用
<canvas id="myCanvas" width="200" height="100"></canvas>
注意: 标签通常需要指定一个id属性 (脚本中经常引用), width 和 height 属性定义的画布的大小.
提示: 你可以在HTML页面中使用多个 canvas 元素.
通过设置边框使canvas画处理的图形显示出来
<canvas id="myCanvas" width="200" height="100" style="border: 1px solid #000000"> </canvas>
使用JavaScript 来绘制图像
let c = document.getElementById('myCanvas'); let ctx = c.getContext('2d'); ctx.fillStyle = '#FF0000'; ctx.fillRect(0, 0, 150, 75);
这里对canvas进行简单的介绍,大家可以进行系统的学习
三、动态验证码的具体实现
- 在项目中创建 SIdentify.vue 文件
代码如下
<template> <div class="s-canvas"> <canvas id="s-canvas" :width="contentWidth" :height="contentHeight" class="canvas"></canvas> </div> </template> <script> export default { name: "SIdentify", props: { identifyCode: { type: String, default: "1234" }, fontSizeMin: { type: Number, default: 35 }, fontSizeMax: { type: Number, default: 35 }, backgroundColorMin: { type: Number, default: 180 }, backgroundColorMax: { type: Number, default: 240 }, colorMin: { type: Number, default: 50 }, colorMax: { type: Number, default: 160 }, lineColorMin: { type: Number, default: 100 }, lineColorMax: { type: Number, default: 200 }, dotColorMin: { type: Number, default: 0 }, dotColorMax: { type: Number, default: 255 }, contentWidth: { type: Number, default: 100 }, contentHeight: { type: Number, default: 30 } }, 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 + ")"; }, transparent () { return "rgb(255,255,255)"; }, drawPic () { let canvas = document.getElementById("s-canvas"); let ctx = canvas.getContext("2d"); ctx.textBaseline = "bottom"; // 绘制背景 ctx.fillStyle = this.randomColor( this.backgroundColorMin, this.backgroundColorMax ); ctx.fillStyle = this.transparent(); 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(-10, 10); // 修改坐标原点和旋转角度 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> <style scoped> .canvas { margin-top: -0.2667rem; } </style>
- 再创建要使用该组件的文件,App.vue
代码如下
<template> <div class="login container"> <input type="text" placeholder="请输入图片验证码" v-model="imgUrlCode"></input> <div class="get-code" @click="refreshCode()"> <s-identify :identifyCode="identifyCode"></s-identify> </div> </div> </template> <script> import SIdentify from "./components/SIdentify.vue"; export default { data () { return { identifyCode: "", // 这里是我们验证码的全部元素,生成的验证码由下面的字符串组成,大家可以随意添加 identifyCodes: "0123456789abcdwerwshdjeJKDHRJHKOOPLMKQ",//绘制的随机 // 图片验证码 imgUrlCode: '', } }, components: { //注册组件 SIdentify }, created () { this.refreshCode() }, methods: { refreshCode () { // 刷新验证码 this.identifyCode = ""; // 4是控制生成验证码的长度 this.makeCode(this.identifyCodes, 4); }, randomNum (min, max) { max = max + 1 return Math.floor(Math.random() * (max - min) + min) }, // 随机生成验证码字符串 makeCode (data, len) { for (let i = 0; i < len; i++) { this.identifyCode += data[this.randomNum(0, data.length - 1)] } }, } } </script> <style> input { width: 120px; height: 30px; } .container { display: flex; justify-content: center; align-items: center; } .get-code { margin-top: 10px; width: 80px; height: 30px; } </style>
这里并未对输入的验证码进行验证,大家可以对输入的验证码 imgUrlCode 和 生成的验证码 identifyCodes 进行对比和验证。
欢迎大家在评论区讨论,一起学习