序文
端末にログインするときに友達が変化に気づいたかどうかはわかりませんがweb
、ログインする前に、アカウントとパスワードを渡してから直接ログインでき、その後、グラフィック認証コード、数値を入力して直接ログインできます。結果動作検証、そしてパズル検証です。この一連の変更は機械の動作を妨げるためですが、私たちにとっては何億ものトラブルがありますが、どうしようもありません。
今日、私たちも億のトラブルを生み出し、ジグソー検証を実現する人になります。
実現原理
実装原理は複雑ではありません。接合材料として必要なのは画像だけです。別のボックスを作成し、それを指定された位置に移動します。指定された範囲に到達すると検証に合格します。そうでない場合は検証に合格します。通らない。
原理がわかったので、始めましょう。
フロントエンドのログインパズル検証を実装する
この記事はcss
主にjavascript
実現に基づいて補足されています。
枠組みを構築する
この機能を実現するには、まずフレームワークを構築する必要があります。
// css
<style>
.check{
width: 400px;
height: 300px;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url(https://img0.baidu.com/it/u=2028084904,3939052004&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500);
}
</style>
// html
<div class="check"></div>
描画すると下の図のようになります。
検証対象領域と検証対象領域を追加
以下の図に示すように、検証のために検証済みエリアと検証済みエリアを追加する必要があります。
ここでは、疑似クラスを使用してこれら 2 つの領域を実装します。
チェックエリア
.check::before{
content: '';
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid #fff;
position: absolute;
top: 100px;
left: 280px;
}
このような検証エリアが用意されています。
チェックしたエリア
background-position
ここでは、検証領域のサイズに応じて検証領域を切り取る必要があります。
background-image
直接継承しbackground-repeat
てbackground-position
検証領域の座標位置(つまり和top
とleft
距離の間の距離)として設定し、background-size
画像のサイズを元のボックスのサイズに設定します。このようにして、検証対象の領域である検証領域の面積を取得します。
.check-child{
content: '';
width: 50px;
height: 50px;
border: 1px solid #fff;
background-image: inherit;
background-repeat: inherit;
background-size: 400px 300px;
background-position: -280px -100px;
position: absolute;
top: 100px;
left: 10px;
}
// html
<!-- 被校验区域 -->
<div class="check-child"></div>
ドラッグバーを追加する
ここで両方の領域の追加が完了しました。ドラッグ バーを追加する必要があります。
まずはドラッグゾーンを追加しましょう。
// css
.drag{
width: 400px;
height: 50px;
background-color: #e3e3e3;
margin-top: 10px;
position: relative;
}
// html
<div class="drag"></div>
ドラッグ領域が使用できるようになったので、ドラッグ可能なボックスと操作手順をドラッグ領域に追加する必要があります。追加しないと、インタラクション効果が不親切になります。
ドラッグ可能なボックスとインタラクティブな指示を追加する
ドラッグ可能なボックスを追加します。
// css
.drag-child{
width: 50px;
height: 50px;
background-color: aquamarine;
z-index: 10;
position: absolute;
top: 0;
left: 0;
}
// html
<!-- 可拖动的盒子 -->
<div class="drag-child"></div>
友好的な対話のために、ドラッグ エリアに操作指示を追加します。
// css
.drag-tips{
display: flex;
align-items: center;
justify-content: end;
width: 95%;
height: 100%;
margin: 0 auto;
font-size: 12px;
color: #8a8a8a;
}
// html
<!-- 可拖动的盒子 -->
<div class="drag-tips">
<span>按住左边按钮向右拖动完成上方图像验证</span>
</div>
バーをドラッグして移動します
このステップでは、ドラッグ ボックスを移動させて、ドラッグ エリア内で左右に自由にドラッグできるようにする必要があります。
// 获取元素实例
const drag = document.querySelector('.drag-child')
// 声明鼠标按下事件
const dragMouseDown = event => {
// 添加鼠标移动事件
document.addEventListener('mousemove', dragMouseMove)
}
// 监听鼠标移动事件
const dragMouseMove = event => {
// 获取当前 x 轴坐标
const {
offsetX } = event
if(offsetX < 0 || offsetX > 350){
return
}
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
offsetX}px)`
}
// 结束鼠标监听事件
const dragMouseUP = event => {
// 移除鼠标移动事件
document.removeEventListener('mousemove', dragMouseMove)
}
// 添加鼠标按下事件
document.addEventListener('mousedown', dragMouseDown)
// 添加鼠标弹起事件
document.addEventListener('mouseup', dragMouseUP)
これで、ボックスを通常どおりドラッグできるようになりましたが、まだいくつかの問題があり、後で解決します。
- プロンプトテキストが選択されます。
- 内側に
拖动区域
ドラッグすると点滅します。
リンケージ領域を確認する
チェックした部分をドラッグして動かしてみます。
// 图形校验
const check = document.querySelector('.check-child')
// 修改被校验区域坐标
check.style.left = `${
offsetX}px`
このようにして、検証済み領域はそれに応じて移動することができ、検証コールバックが渡されたことを示すメソッドを宣言します。
// 通过校验回调
const success = () => {
console.log('通过校验');
}
// 监听鼠标移动事件
const dragMouseMove = event => {
// 获取当前 x 轴坐标
const {
offsetX } = event
if(offsetX < 0 || offsetX > 350){
return
}
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
offsetX}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
offsetX}px)`
if(offsetX >= 278 && offsetX <= 285){
// 执行回调
success()
}
}
インタラクティブなアニメーションを追加する
ここでは、マウスがモニターの外に移動したときのアニメーションを追加し、検証に失敗したときにマウスを初期位置に戻します。
@keyframes move {
to {
transform: translateX(0);
}
}
// 结束鼠标监听事件
const dragMouseUP = event => {
// 移除鼠标移动事件
document.removeEventListener('mousemove', dragMouseMove)
// 获取当前 x 轴坐标
const {
offsetX } = event
if(offsetX < 278 || offsetX > 285){
// 修改可移动盒子的 x 轴坐标
drag.style.animation = 'move 0.5s ease-in-out'
// 修改被校验区域坐标
check.style.animation = 'move 0.5s ease-in-out'
// 动画结束监听回调
const animationEnd = ()=>{
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
0}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
0}px)`
// 清除动画属性
drag.style.animation = ''
check.style.animation = ''
// 移出动画结束监听
document.removeEventListener("animationend", animationEnd)
}
// 添加动画结束监听
document.addEventListener("animationend", animationEnd)
}
}
検証に失敗してマウスを放すと、マウスは自動的に初期位置に戻ります。
従来の問題を解決する
1. プロンプトテキストが選択されます
これをプロンプト テキストのスタイルに追加しuser-select: none;
、テキストの選択を無効にします。
/* 提示文字说明 */
.drag-tips{
display: flex;
align-items: center;
justify-content: end;
width: 95%;
height: 100%;
margin: 0 auto;
font-size: 12px;
color: #8a8a8a;
user-select: none;
z-index: 1;
position: absolute;
top: 0;
left: 0;
}
2.拖动区域
内側をと点滅します
offsetX
これまでのやり方を変えますpageX
。ここで、マージンオフセットの問題に注意する必要があります。
// 监听鼠标移动事件
const dragMouseMove = event => {
console.log(event);
// 获取当前 x 轴坐标
const {
pageX } = event
if(pageX < 0 || pageX > 350){
return
}
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
pageX}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
pageX}px)`
if(pageX >= 278 && pageX <= 285){
// 执行回调
success()
}
}
// 结束鼠标监听事件
const dragMouseUP = event => {
// 移除鼠标移动事件
document.removeEventListener('mousemove', dragMouseMove)
// 获取当前 x 轴坐标
const {
pageX } = event
if(pageX < 278 || pageX > 285){
// 修改可移动盒子的 x 轴坐标
drag.style.animation = 'move 0.5s ease-in-out'
// 修改被校验区域坐标
check.style.animation = 'move 0.5s ease-in-out'
// 动画结束监听回调
const animationEnd = ()=>{
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
0}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
0}px)`
// 清除动画属性
drag.style.animation = ''
check.style.animation = ''
// 移出动画结束监听
document.removeEventListener("animationend", animationEnd)
}
// 添加动画结束监听
document.addEventListener("animationend", animationEnd)
}
}
レンダリング
レンダリングを見てみましょう。
完全なコード
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>drag</title>
<style>
*{
margin: 0;
padding: 0;
}
body{
padding: 20px;
}
/* 图形拼图验证码 */
.check{
width: 400px;
height: 300px;
background-repeat: no-repeat;
background-size: 100% 100%;
background-image: url(https://img0.baidu.com/it/u=2028084904,3939052004&fm=253&fmt=auto&app=138&f=JPEG?w=889&h=500);
position: relative;
}
.check::before{
content: '';
width: 50px;
height: 50px;
background: rgba(0, 0, 0, 0.5);
border: 1px solid #fff;
position: absolute;
top: 100px;
left: 280px;
}
.check-child{
content: '';
width: 50px;
height: 50px;
border: 1px solid #fff;
background-image: inherit;
background-repeat: inherit;
background-size: 400px 300px;
background-position: -280px -100px;
position: absolute;
top: 100px;
left: 0;
}
/* 拖动条 */
.drag{
width: 400px;
height: 50px;
background-color: #e3e3e3;
margin-top: 10px;
position: relative;
}
/* 可拖动的盒子 */
.drag-child{
width: 50px;
height: 50px;
background-color: aquamarine;
z-index: 10;
position: absolute;
top: 0;
left: 0;
}
/* 提示文字说明 */
.drag-tips{
display: flex;
align-items: center;
justify-content: end;
width: 95%;
height: 100%;
margin: 0 auto;
font-size: 12px;
color: #8a8a8a;
user-select: none;
z-index: 1;
position: absolute;
top: 0;
left: 0;
}
@keyframes move {
to {
transform: translateX(0);
}
}
</style>
</head>
<body>
<!-- 图形校验区域 -->
<div class="check">
<!-- 被校验区域 -->
<div class="check-child"></div>
</div>
<!-- 拖动条 -->
<div class="drag">
<!-- 操作说明 -->
<div class="drag-tips">
<span>按住左边按钮向右拖动完成上方图像验证</span>
</div>
<!-- 可拖动的盒子 -->
<div class="drag-child"></div>
</div>
</body>
<script>
// 获取元素实例
const drag = document.querySelector('.drag-child')
// 图形被校验区域
const check = document.querySelector('.check-child')
// 通过校验回调
const success = () => {
console.log('通过校验');
}
// 声明鼠标按下事件
const dragMouseDown = event => {
// 添加鼠标移动事件
document.addEventListener('mousemove', dragMouseMove)
}
// 监听鼠标移动事件
const dragMouseMove = event => {
// 获取当前 x 轴坐标
const {
pageX } = event
if(pageX < 0 || pageX > 350){
return
}
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
pageX}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
pageX}px)`
if(pageX >= 278 && pageX <= 285){
// 执行回调
success()
}
}
// 结束鼠标监听事件
const dragMouseUP = event => {
// 移除鼠标移动事件
document.removeEventListener('mousemove', dragMouseMove)
// 获取当前 x 轴坐标
const {
pageX } = event
if(pageX < 278 || pageX > 285){
// 修改可移动盒子的 x 轴坐标
drag.style.animation = 'move 0.5s ease-in-out'
// 修改被校验区域坐标
check.style.animation = 'move 0.5s ease-in-out'
// 动画结束监听回调
const animationEnd = ()=>{
// 修改可移动盒子的 x 轴坐标
drag.style.transform = `translateX(${
0}px)`
// 修改被校验区域坐标
check.style.transform = `translateX(${
0}px)`
// 清除动画属性
drag.style.animation = ''
check.style.animation = ''
// 移出动画结束监听
document.removeEventListener("animationend", animationEnd)
}
// 添加动画结束监听
document.addEventListener("animationend", animationEnd)
}
}
// 添加鼠标按下事件
document.addEventListener('mousedown', dragMouseDown)
// 添加鼠标弹起事件
document.addEventListener('mouseup', dragMouseUP)
</script>
</html>
やっと
この記事は以上です前端实现登录拼图验证
. この機能は通常ログイン時に使用します。この記事のケースは普通に使えます。
この記事で実装されているコードには、ドラッグ禁止領域にドラッグできるという従来の問題があります。