使用html和js和svg实现的一个简单小练习登录页面中的验证码,大概功能主要是:
点击看不清换一张会重新生成验证码,验证码中包含数字、线条、字母。该验证码是通过svg实现。详细的解释和代码步骤我都注释在下面的代码中的,请君一阅。
【注:仅作自己查看和分享学习之用】
【效果如图】
代码如下:
登录页面
/* 我这里重置了所有样式,如要使用代码,记得注意重置样式问题 */
登录页面!
let inpEle = document.querySelectorAll("input");
let btn = document.getElementsByTagName("button")[0];
let form = document.getElementsByTagName("form")[0];
let svgEle = document.getElementsByTagName("svg")[0];
let shuaxin = document.getElementsByClassName("shuaxin")[0];
btn.addEventListener("click", function (event) {
//获取用户的数据
let username = inpEle[0].value;
let pwd = inpEle[1].value;
//获取验证码框的信息
let code = svgEle.dataset.str;
let admin = JSON.parse(localStorage.getItem("users"));
let arr = admin.filter(item => item.username == username && item.password == pwd);
if (arr.length > 0) {
//把输入框的输入的字母全都转成小写与svg标签里面的字符串进行对比
//因为str基础数据字符串里就全是小写字母,在渲染的时候其中有部分会随机渲染成大写字母,但这并不影响最开始拿到的那个随机生成的字符串
if (inpEle[2].value.toLowerCase() === code) {
alert("恭喜您登录成功!");
form.action = "./index.html";
} else {
alert("验证码错误!");
inpEle[2].value = "";
codeRender();
}
} else {
alert("账号或密码错误,请重新输入!");
[...inpEle].forEach(item => item.value = "");
codeRender();
event.preventDefault();
}
});
//画验证码
function codeRender() {
//进来就清空验证码框的样式
svgEle.innerHTML = "";
let clientWidth = svgEle.clientWidth;
let clientHeight = svgEle.clientHeight;
//创建文档碎片
let docFra = document.createDocumentFragment();
//添加线条节点到svg节点中
let lines = createLineNode(5, 5, clientHeight, clientWidth, docFra);
svgEle.appendChild(lines);
//添加文本节点到svg节点中
let texts = createTextNode(5, clientWidth, docFra);
svgEle.appendChild(texts[0]);
//给svg标签加一个自定义属性
svgEle.dataset.str = texts[1];
}
codeRender();
//随机字母和数字
function createTextNode(num, clientWidth, docFra) {
//获取字符水平方向可以移动的距离
let maxX = parseInt(clientWidth / num);
console.log(maxX);
let str = ``;
for (let i = 0; i < num; i++) {
let textNode = document.createElementNS("http://www.w3.org/2000/svg", "text");
//获取字符
let char = getChar();
//不区分大小写
//用str拼接所有的字符,为了方便登录时进行验证
str += char;
let re = /^[a-z]$/img;
//判断字符是否为字母,且会随机变大写字母
//test方法查找:在char里面查找re;返回Boolean值,满足返回true,不满足返回false
//getRandom(0, 1):意思是让字母进来了随机成为0或者1,因为0会直接隐式转换为false就进入不了这个判断,
//所以只有当它随机为1时,才会进入if,并转换为大写字母。
if (re.test(char) && getRandom(0, 1)) {
//设置字母为大写字母
char = char.toUpperCase();
}
//把字符添加到节点中
textNode.innerHTML = char;
//设置字符的基线位置
console.log(maxX * i);
console.log(maxX * (i + 1) - 30);
textNode.setAttribute("x", getRandom(maxX * i, Math.abs(maxX * (i + 1) - 30)));
textNode.setAttribute("y", 30);
textNode.style.fontSize = 30 + "px";
textNode.style.transform = `rotate(${getRandom(0, 5)}deg)`;
//线条的颜色样式
textNode.style.fill = `rgba(${getRandom(0, 255)},${getRandom(0, 255)},${getRandom(0, 255)},1)`;
docFra.appendChild(textNode);
}
return [docFra, str];
}
//字符组
function getChar() {
let str = `0123456789abcdefghijklmnopqrstuvwxyz`;
return str[getRandom(0, str.length - 1)];
}
//随机线条
function createLineNode(num, lineWidth, clientHeight, clientWidth, docFra) {
for (let i = 0; i < num; i++) {
//添加线条
let line = document.createElementNS("http://www.w3.org/2000/svg", "line");
//起始坐标和终止坐标
line.setAttribute("x1", getRandom(0, clientWidth));
line.setAttribute("y1", getRandom(0, clientHeight));
line.setAttribute("x2", getRandom(0, clientWidth));
line.setAttribute("y2", getRandom(0, clientHeight));
line.style.stroke = `rgba(${getRandom(0, 255)},${getRandom(0, 255)},${getRandom(0, 255)},${getRandom(0, 10) / 10})`;
line.style.strokeWidth = getRandom(0, lineWidth);
//把线条添加到文档碎片中去
docFra.appendChild(line);
}
//返回这个文档碎片
return docFra;
}
//刷新文本
shuaxin.addEventListener("click", function () {
//点击刷新文本,重新渲染
codeRender();
});
//获取随机数
function getRandom(min, max = 0) {
if (min > max) {
[min, max] = [max, min];
}
return parseInt(Math.random() * (max - min + 1)) + min;
}