jquery
实现文字点选验证码
git地址:点击获取源码
一、功能说明(文字点选验证码)
- 词组库内存在大量3~6字随机词组,
- 从词组库内随机找出一组词组,随机展现在显示区
- 点击按钮,弹出验证码区域
- 将词组内的随机数量文字随机顺序作为验证文本进行校验
- 点击文字添加标记并计数,当点击次数与验证文本数量一致,自动校验
- 验证通过后,提示成功,关闭验证区域
- 验证失败,提示失败,刷新验证码
- 点击显示区内刷新按钮,刷新验证码
二. 效果图:
三、代码:
- 验证区
html
:index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入验证区样式 -->
<link rel="stylesheet" type="text/css" href="css/index.css" />
<style>
.my-container {
position: relative;
top: 20px;
left: 50px;
}
</style>
</head>
<body>
<div class="my-container">
<input type="text"><button id="btn">点击触发验证码</button>
</div>
<!-- 验证码区域 -->
<div id="verification">
<!-- 刷新 -->
<div class="refresh"></div>
<!-- 验证结果 -->
<div id="resultBox"></div>
<!-- 验证词组显示区 -->
<div id="box"></div>
</div>
<script src="js/jquery-1.9.1.min.js"></script>
<!-- 引入验证区js -->
<script src="js/index.js" type="text/javascript" charset="utf-8"></script>
<script>
/**
* 点击按钮显示验证区,初始化验证区
*/
$('#btn').click(() => {
$('#verification').show()
init();
})
</script>
</body>
</html>
- 验证区
js
:index.js
// TODO获取词库
$(function () {
fetch("/js/data.json")
.then((response) => response.json()) // 解析JSON响应
.then((response) => {
textData = response.data;
})
.catch((error) => console.error("Error:", error));
});
/**
* @constant box 容器
* @variate place 文字分散在容器中的随机位置
* @variate textData 文字库集合
* @variate verifyWord 需要校验的词组,用于渲染布局
* @constant minVerifyWordLen 随机文字最小数量
* @variate verifyText 需要校验的随机文字,用于展示
* @variate verifyTextIdxs 需要校验的文本,取verifyText的index值
* @variate verifyClickCount 点击校验文字的次数,达到verifyTextIdxs长度进行校验
* @variate selectedIdxs 选中文字的index集合
*/
const box = $("#box");
let place = [
{ left: "0px", top: "0px" },
{ left: "120px", top: "0px" },
{ left: "240px", top: "0px" },
{ left: "0px", top: "90px" },
{ left: "120px", top: "90px" },
{ left: "240px", top: "90px" },
];
let textData = [];
let verifyWord = "";
const minVerifyWordLen = 3;
let verifyText = "";
let verifyTextIdxs = [];
let verifyClickCount = 0;
let selectedIdxs = [];
/**
* @function getVerifyWord 获取随机校验词组
*/
function getVerifyWord() {
return textData[Math.floor(Math.random() * (textData.length - 1))];
}
/**
* @function getVerifyText 获取随机校验文字
*/
function getVerifyText() {
// 随机选取校验文字数量
let lenRandom = Math.ceil(Math.random() * verifyWord.length);
if (lenRandom < minVerifyWordLen) {
lenRandom = minVerifyWordLen;
}
const verifyArray = verifyWord.split("");
const result = [];
// 获取随机需要校验的文字
for (let i = 0; i < lenRandom; i++) {
let index = Math.floor(Math.random() * verifyArray.length);
result.push(verifyArray[index]);
verifyArray.splice(index, 1); // 移除已选的元素以避免重复
}
return result.join("");
}
/**
* @function getVerifyText 获取校验文字的idx
*/
function getVerifyTextIdxs() {
const wordArray = verifyWord.split("");
const textArray = verifyText.split("");
const result = [];
for (let text of textArray) {
const idx = wordArray.findIndex((word) => word === text);
result.push(idx);
}
return result;
}
/**
* @function clear 重置
*/
function clear() {
box.empty();
verifyWord = getVerifyWord();
verifyText = getVerifyText();
verifyTextIdxs = getVerifyTextIdxs();
verifyClickCount = 0;
selectedIdxs = [];
$("#resultBox").html(`请依次点击: <span>${verifyText}</span>`);
place.sort(() => {
return Math.random() - 0.5;
});
}
/**
* @function init 初始化
*/
function init() {
// 重置内容
clear();
verifyWord.split("").map((text, idx) => {
createVerifyBox(text, idx);
});
/**
* 创建存放每个校验文字的容器
* @param {string} text 文字
* @param {number} idx 索引
* @attribute {number} index 文字标签的index值
* @attribute {string: true | false } judge 判断标签是否被点击
*/
function createVerifyBox(text, idx) {
//创建box分割的div容器
let divEl = $('<div class="item"></div>');
divEl.css({
left: place[idx].left,
top: place[idx].top,
});
//创建span标签存储校验文字
let spanEl = $(`<span class="spanEl">${text}</span>`);
divEl.append(spanEl);
box.append(divEl);
addSpanElCss(divEl, spanEl);
// 添加属性,
// 用于存入selectedIdxs
spanEl.data("index", idx);
spanEl.data("judge", "true");
}
/**
* 添加span项样式
*/
function addSpanElCss(divEl, spanEl) {
const lt = divEl.width() - spanEl.width() - 10;
const rt = divEl.height() - spanEl.height() - 10;
let left = Math.floor(Math.random() * lt);
let top = Math.floor(Math.random() * rt);
spanEl.css({
left: left + "px",
top: top + "px",
});
}
//span点击事件
$("#box .item span").click(function (e) {
if ($(this).data("judge") == "true") {
selectedIdxs.push($(this).data("index"));
console.log(selectedIdxs, "selectedIdxs", verifyTextIdxs);
$(this).data("judge", "false");
verifyClickCount++;
appendRadio(e);
// 验证
if (verifyClickCount === verifyTextIdxs.length) {
getVerifyResult();
}
}
});
//点击事件,生成圆点
function appendRadio(e) {
const radioEl = $(`<div class='radio'>${verifyClickCount}</div>`);
box.append(radioEl);
const wt = radioEl.width() / 2;
const ht = radioEl.height() / 2;
radioEl.css({
left: e.pageX - box.offset().left - wt + "px",
top: e.pageY - box.offset().top - ht + "px",
});
}
}
/**
* @function getVerifyResult 获取校验结果
*/
function getVerifyResult() {
if (selectedIdxs.join() == verifyTextIdxs.join()) {
$("#resultBox span").html("验证成功");
$("#resultBox span").css("color", "#1abd6c");
setTimeout(() => {
$("#verification").hide();
}, 500);
// TODO 验证成功后操作
} else {
$("#resultBox span").html("验证失败");
$("#resultBox span").css("color", "red");
setTimeout(() => {
init();
}, 500);
}
verifyClickCount = 0;
}
/**
* @function 刷新
*/
$(".refresh").click(() => {
init();
});
- 验证区
css
:index.css
#verification {
position: absolute;
top: 60px;
left: 50px;
display: none;
}
/* 刷新 */
#verification .refresh{
position: absolute;
top: 50px;
right: 10px;
z-index: 10;
width: 28px;
height: 28px;
cursor: pointer;
background-image: url("/img/refresh.png");
background-size: 100% 100%;
}
#box{
position: relative;
width: 360px;
height: 180px;
padding: 0 20px;
border-radius: 10px;
background-image: url("/img/bg.png");
background-repeat: no-repeat;
}
#box .item{
position: absolute;
width: 120px;
height: 90px;
}
#box .radio{
position: absolute;
z-index: 10;
width: 30px;
height: 30px;
line-height: 30px;
text-align: center;
border-radius: 50%;
color: #fff;
background-color: #1abd6c;
}
#box span{
font-size: 40px;
position: absolute;
z-index: 4;
color: #4463cb;
font-weight: bold;
}
#box span:hover{
cursor: pointer;
}
#resultBox{
height: 40px;
font-size: 18px;
line-height: 40px;
}
#resultBox span{
font-size: 22px;
font-weight: bold;
color: #1f1f1f;
}
- 词库文件:
data.json
{
"data": [
"快乐的大脚",
"阖家快乐",
"祝福您",
"萌新的快乐",
"彩色溜",
"恭喜发财祝您",
"假期愉快",
"天天开心呀",
"今天是好天气",
"美丽的神话",
"加菲猫",
"小马宝利",
"记得加油呀",
"巴啦啦小魔仙",
"大头儿子",
"疯狂动物城"
]
}