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>
- 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.
- 验证区
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();
});
- 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.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 验证区
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;
}
- 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.
- 词库文件:
data.json