返回
从B站官网实现滑动拼图验证码中的三点体会
前端
2023-09-03 13:33:45
为什么要弄这个滑动拼图验证码呢?因为相对来说,前端的实现比较复杂和深入,相比12306的图片验证码而言,对前端技术要求高得多。另外,滑动拼图验证码是众多验证码中最难破解的一种,如今已经广泛地应用在各种网站中。
先来看看最后效果:
(效果演示截图)
接下来,让我们一步步分解代码。
1. 原理
拼图验证码的原理并不复杂,只需通过拖动鼠标来将拼图块滑到正确的位置即可。当拼图块被拖动到正确位置时,验证码将被验证通过。
2. 实现方法
1)HTML 结构
<div class="puzzle-container">
<div class="puzzle-image-container">
<img src="puzzle-image.jpg" alt="Puzzle Image">
</div>
<div class="puzzle-pieces-container">
<div class="puzzle-piece" data-x="0" data-y="0"></div>
<div class="puzzle-piece" data-x="100" data-y="0"></div>
<div class="puzzle-piece" data-x="200" data-y="0"></div>
<div class="puzzle-piece" data-x="0" data-y="100"></div>
<div class="puzzle-piece" data-x="100" data-y="100"></div>
<div class="puzzle-piece" data-x="200" data-y="100"></div>
<div class="puzzle-piece" data-x="0" data-y="200"></div>
<div class="puzzle-piece" data-x="100" data-y="200"></div>
<div class="puzzle-piece" data-x="200" data-y="200"></div>
</div>
</div>
2)CSS 样式
.puzzle-container {
width: 300px;
height: 300px;
}
.puzzle-image-container {
width: 300px;
height: 300px;
overflow: hidden;
}
.puzzle-image {
width: 600px;
height: 600px;
}
.puzzle-pieces-container {
width: 300px;
height: 300px;
position: relative;
}
.puzzle-piece {
width: 100px;
height: 100px;
position: absolute;
cursor: pointer;
}
3)JavaScript 代码
const puzzleContainer = document.querySelector('.puzzle-container');
const puzzleImageContainer = document.querySelector('.puzzle-image-container');
const puzzleImage = document.querySelector('.puzzle-image');
const puzzlePiecesContainer = document.querySelector('.puzzle-pieces-container');
const puzzlePieces = document.querySelectorAll('.puzzle-piece');
// 拼图块的原始位置
const puzzlePieceOriginalPositions = [];
// 拼图块的当前位置
const puzzlePieceCurrentPositions = [];
// 记录拼图是否完成
let puzzleCompleted = false;
// 为每个拼图块添加事件监听器
puzzlePieces.forEach((puzzlePiece) => {
puzzlePiece.addEventListener('mousedown', (e) => {
// 记录拼图块的原始位置
puzzlePieceOriginalPositions.push({
x: e.clientX,
y: e.clientY,
});
// 记录拼图块的当前位置
puzzlePieceCurrentPositions.push({
x: puzzlePiece.offsetLeft,
y: puzzlePiece.offsetTop,
});
// 开始拖动拼图块
puzzlePiece.style.transition = 'none';
puzzlePiece.style.zIndex = 100;
// 鼠标移动时,更新拼图块的位置
document.addEventListener('mousemove', (e) => {
puzzlePiece.style.left = `${e.clientX - puzzlePieceOriginalPositions[0].x + puzzlePieceCurrentPositions[0].x}px`;
puzzlePiece.style.top = `${e.clientY - puzzlePieceOriginalPositions[0].y + puzzlePieceCurrentPositions[0].y}px`;
});
// 鼠标松开时,停止拖动拼图块
document.addEventListener('mouseup', () => {
puzzlePiece.style.transition = 'all 0.2s ease-in-out';
puzzlePiece.style.zIndex = 0;
// 检查拼图是否完成
if (isPuzzleCompleted()) {
puzzleCompleted = true;
// 显示提示信息
alert('拼图完成!');
}
// 清空数组
puzzlePieceOriginalPositions.length = 0;
puzzlePieceCurrentPositions.length = 0;
});
});
});
// 检查拼图是否完成
function isPuzzleCompleted() {
for (let i = 0; i < puzzlePieces.length; i++) {
if (puzzlePieces[i].offsetLeft !== puzzlePieces[i].dataset.x || puzzlePieces[i].offsetTop !== puzzlePieces[i].dataset.y) {
return false;
}
}
return true;
}
3. 难点与解决方法
在实现这个功能时,我遇到了几个难点:
- 如何生成拼图块?
为了生成拼图块,我使用了 HTML5 的 <canvas>
元素。首先,我将原图绘制到 <canvas>
元素上,然后使用 JavaScript 代码将 <canvas>
元素分成 9 个部分,并为每个部分创建一个拼图块。
- 如何拖动拼图块?
为了拖动拼图块,我使用了 JavaScript 代码。首先,我获取拼图块的原始位置,然后使用 mousemove
事件监听器来更新拼图块的位置。当鼠标松开时,我停止拖动拼图块。
- 如何判断拼图是否完成?
为了判断拼图是否完成,我使用了 JavaScript 代码。首先,我获取所有拼图块的当前位置,然后将它们与拼图块的原始位置进行比较。如果所有拼图块的当前位置都与拼图块的原始位置相同,则拼图完成。
4. 总结
通过这个项目,我学到了很多东西。我不仅学会了如何实现滑动拼图验证码,还学会了如何使用 HTML5 的 <canvas>
元素和 JavaScript 代码来创建交互式网页。