1.原理
后端预先保存n张图片用来做滑动验证码的素材,然后在图片上面随机取一块固定大小的小图片作为滑动的素材,然后记录小图片相对于大图的位置,也就是小图上边距和大图上边距之前的距离(x座标),小图左边距和大图左边距的距离(y座标)。
前端先请求图片资源,后端返回大图、小图和小图的(y座标),当用户拖动小图后,获取到小图的x座标,将此时小图的x,y座标返给后端做验证。
<!--html-->
<!--滑动验证码-->
<div class="img_bg" v-if="showImgContent">
<!--滑动容器-->
<div class="sliderImg" >
<!--大图-->
<img :src="save_big_url" alt="" class="big_img">
<!--小图-->
<img :src="save_small_url"
alt="" class="small_img"
ref="small_img"
@mousedown="move"
>
<div class="img_tip">请滑动验证码进行验证。</div>
</div>
</div>
//js
data() {
return {
showImgContent: false,//是否展示图片验证码
isCheckImg: false,// 是否使用滑动验证码
positionX: 0, // 小图相对大图的左边距
positionY: 0,// 小图相对大图的上边距
save_big_url: "",//小图url
save_small_url: "",//大图url
}
}
methods:{
// 获取验证图片和参数
async mixVerifyCode(x = "") { // x为空,请求图片和参数,验证时传x座标
let result;
await httpServer("获取验证码图片和y座标", {
xvalue: x
})
.then((res) => {
result = res;
})
.catch((err) => {
})
return result;
},
// 渲染图片
showImg() {
this.mixVerifyCode().then((res) => {
// 给图片URL赋值
this.save_big_url = res.save_big_url
this.save_small_url = res.save_small_url
// 初始化小图的位置
this.$refs.small_img.style.top = `${res.yvalue}px`;
this.$refs.small_img.style.left = `10px`;
});
},
// 滑动验证码
move(e) {
let odiv = e.target; //获取目标元素(小图)
//算出鼠标相对元素的位置
let disX = e.clientX - odiv.offsetLeft;
let disY = e.clientY - odiv.offsetTop;
// 鼠标移动时
document.onmousemove = (e) => { //鼠标按下并移动的事件
if (e.preventDefault) e.preventDefault();
//用鼠标的位置减去鼠标相对元素的位置,得到元素的位置
let left = e.clientX - disX;
let top = e.clientY - disY;
//绑定元素位置到positionX和positionY上面
this.positionX = left;
this.positionY = top;
let bigImg = document.getElementsByClassName("big_img")[0];
const bigX = bigImg.clientWidth - odiv.offsetWidth;
left = Math.min(Math.max(0, left), bigX);
//移动当前元素
odiv.style.left = left + 'px';
};
// 鼠标按键释放时
document.onmouseup = (e) => {
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
e.cancelBubble = true;
document.onmousemove = null;
document.onmouseup = null;
// 计算小图x值
const xvalue = e.clientX - e.offsetX - document.getElementsByClassName("big_img")[0].getBoundingClientRect().x;
// 想后端发起验证请求
this.mixVerifyCode(parseInt(xvalue).toString()).then((res) => {
if (res.is_success) {
// 验证通过
this.showImgContent = false;
this.isCheckImg = true;
// 继续你的业务逻辑
} else {
// 验证未通过
this.isCheckImg = false;
this.showImg();// 刷新图片验证码
odiv.style.left = "0px";
}
})
};
}
}