canvas实现滑块验证码,无需任何插件
无需插件,简简单单几行代码实现滑块验证码
话不多说,老规矩,先上Demo,预览地址:blogai.cn
再放几张预览图:
该功能的实现大概有以下几步:
- canvas 创建两个一样的画布,储存验证图
- 相同坐标通过fill,clip截取两个验证块
- 监听鼠标按下事件,记录初始X坐标
- 监听鼠标移动事件,记录下移动坐标,验证块随着移动
- 监听鼠标松开事件,记录结束X坐标
- 对比移动距离和裁剪时的x坐标
- 判断差值是否可忽略
const canvas = document.getElementById('canvas'),
block = document.getElementById('block');
let ctx_c = canvas.getContext('2d'),
ctx_b = block.getContext('2d'),
img = document.createElement('img');
img.src = 'car.jpg';
img.onload = function () {
ctx_c.drawImage(img, 0, 0, canvas.width, canvas.height);
ctx_b.drawImage(img, 0, 0, canvas.width, canvas.height);
let l = 40, //拼接块边长
x = 150 + Math.random() * (canvas.width - 150 - l), //裁剪横坐标,这样可以保证裁剪的拼接块横坐标在150以后,保证充分拖动距离
y = 10 + Math.random() * (canvas.height - l - 10); // y轴坐标
//裁剪拼接块
function cut_i(ctx) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y + l);
ctx.lineTo(x + l, y + l);
ctx.lineTo(x + l, y);
ctx.clip()
}
//裁剪主画布
function fill_i(ctx) {
// ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y + l);
ctx.lineTo(x + l, y + l);
ctx.lineTo(x + l, y);
ctx.fillStyle = '#306e7c'; //这里无所谓,随便填
ctx.globalCompositeOperation = 'xor'; //使裁剪区域透明
ctx.fill()
}
cut_i(ctx_b);
fill_i(ctx_c);
let mousemove = false,
starX = 0;
move_block.addEventListener('mousedown', function (e) { //监听鼠标按下
e.preventDefault();
mousemove = true;
starX = e.clientX //记录开始时的坐标
});
move_block.addEventListener('mousemove', function (e) {//监听鼠标移动
if (mousemove) {
let move_x = e.clientX - starX; //移动距离
if (move_x > canvas.width - l) {
move_x = canvas.width - l;
} else if (move_x < 0) {
move_x = 0;
}
block.style.left = move_x + 'px';
move.style.left = move_x + 'px';
background_.style.left = (move_x - 400) + 'px'; //overflow:hidden 藏在外面的绿色背景
move_block.addEventListener('mouseup', function (res) {//鼠标松开
if (Math.abs(move_x - x) < 2) {//可接受差错值:大于小于2
mousemove = false;
background_.style.left = 0;
success.style.zIndex = 1;
} else {
move_x = 0;
mousemove = false;
block.style.left = 0;
move.style.left = 0;
background_.style.left = '-400px';
}
})