终于实现滑动拼图验证码,vue

缘由:之前看哔哩哔哩官网登录的时候有一个拼图验证码,很好奇怎么去实现。然后就想着自己弄一个。先给大家看我的最终效果。后面再一点点拆解代码。

8f7fce7292dd42968558dbc8df5ac7c1


为什么想着写这个功能呢,主要在于拼图验证码在前端这里会比较复杂并且深入。相比文字拼写,12306的图片验证码都没有拼图验证码对前端的要求来的复杂,和难。

我总结下知识点:

1、弹窗功能

2、弹窗基于元素定位

3、元素拖动

4、canvas绘图

5、基础逻辑

一、弹窗和弹窗组件

抱歉,这里我偷懒了直接用了elementUI的el-popover组件,所以小伙伴不懂的直接看elementUI官网的说明。

我个人也研究和编写了这块的组件功能(基于popper.js)

二、编写基础结构

这块属于html的基础内容,也就标题党了

三、canvas绘制图片

1、canvas绘制外部img图片

代码:

let?mainDom?=?document.querySelector("#codeImg");let?bg?=?mainDom.getContext("2d");let?width?=?mainDom.width;let?height?=?mainDom.height;let?blockDom?=?document.querySelector("#sliderBlock");let?block?=?blockDom.getContext("2d");
//重新赋值,让canvas进行重新绘制
blockDom.height?=?height;
mainDom.height?=?height;let?imgsrc?=?require("../assets/images/back.jpg");let?img?=?document.createElement("img");
img.style.objectFit?=?"scale-down";
img.src?=?imgsrc;
img.onload?=?function()?{
?bg.drawImage(img,?0,?0,?width,?height);?block.drawImage(img,?0,?0,?width,?height);
};复制代码

这里我绘制了两个canvas,因为一个是背景一个是滑块

核心在于

let?mainDom?=?document.querySelector("#codeImg");let?imgsrc?=?require("../assets/images/back.jpg");let?bg?=?mainDom.getContext("2d");let?img?=?document.createElement("img");
img.onload?=?function()?{
?bg.drawImage(img,?0,?0,?width,?height);
};
复制代码

2、canvas绘制滑块部分

就是这个图,这个有一些知识点,不难,但是很复杂。

a7864a1c56964775927078247a3e92bb


代码部分:

drawBlock(ctx,?xy?=?{?x:?254,?y:?109,?r:?9?},?type)?{
?let?x?=?xy.x,
?y?=?xy.y,
?r?=?xy.r,
?w?=?40;
?let?PI?=?Math.PI;?//绘制
?ctx.beginPath();?//left
?ctx.moveTo(x,?y);?//top
?ctx.arc(x?+?(w?+?5)?/?2,?y,?r,?-PI,?0,?true);
?ctx.lineTo(x?+?w?+?5,?y);?//right
?ctx.arc(x?+?w?+?5,?y?+?w?/?2,?r,?1.5?*?PI,?0.5?*?PI,?false);
?ctx.lineTo(x?+?w?+?5,?y?+?w);?//bottom
?ctx.arc(x?+?(w?+?5)?/?2,?y?+?w,?r,?0,?PI,?false);
?ctx.lineTo(x,?y?+?w);
?ctx.arc(x,?y?+?w?/?2,?r,?0.5?*?PI,?1.5?*?PI,?true);
?ctx.lineTo(x,?y);?//修饰,没有会看不出效果
?ctx.lineWidth?=?1;
?ctx.fillStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.strokeStyle?=?"rgba(255,?255,?255,?0.5)";
?ctx.stroke();
?ctx[type]();
?ctx.globalCompositeOperation?=?"xor";
}复制代码

解释下:

参数是传入canvas对象

x,y轴数据

剪切还是填充的canvas函数(fill,clip)

绘制难点:(很重要,不然你没法理解它怎么绘制的)

绘制主要是需要理解这里的绘制是根据你设置一个起始点坐标,然后你绘制第二次的时候线就会连接到第二个点,依次连接最后回到原点就形成一个完整的图形。

b96e9b6c43f34ecfa9868d1eebba350b


用的是arc参数,主要是看这个图

fill是用于填充绘制的部分,clip是裁剪出绘制的部分,利用这个就可以出现一个扣掉的图片和一个裁剪出来的图片。

完成之后就是我的那个函数了。大家可以直接拿去用。

3、让元素跟随鼠标点击之后滑动

这里其实原理非常简单,就是有一个注意点。

原理:

鼠标点击之后记录当前坐标,然后随着(mousemove)滚动的时候修改元素的left和top值就行了。

还有一点就是鼠标快速滑动会导致丢失滑动效果,这里需要用document,不能是元素级别的监听。

元素上面我只需要鉴定按下mousedown

代码:

//鼠标按下drag(e)?{?console.log("鼠标按下",?e);?let?dom?=?e.target;?//dom元素
?let?slider?=?document.querySelector("#sliderBlock");?//滑块dom
?const?downCoordinate?=?{?x:?e.x,?y:?e.y?};?//正确的滑块数据
?let?checkx?=?Number(this.slider.mx)?-?Number(this.slider.bx);?//x轴数据
?let?x?=?0;?const?move?=?moveEV?=>?{
?x?=?moveEV.x?-?downCoordinate.x;?//y?=?moveEV.y?-?downCoordinate.y;
?if?(x?>=?251?||?x?<=?0)?return?false;
?dom.style.left?=?x?+?"px";?//dom.style.top?=?y?+?"px";
?slider.style.left?=?x?+?"px";
?};?const?up?=?()?=>?{?document.removeEventListener("mousemove",?move);?document.removeEventListener("mouseup",?up);
?dom.style.left?=?"";?console.log(x,?checkx);?let?max?=?checkx?-?5;?let?min?=?checkx?-?10;?//允许正负误差1
?if?((max?>=?x?&&?x?>=?min)?||?x?===?checkx)?{?console.log("滑动解锁成功");?this.puzzle?=?true;?this.tips?=?"验证成功";
?setTimeout(()?=>?{?this.visible?=?false;
?},?500);
?}?else?{?console.log("拼图位置不正确");?this.tips?=?"验证失败,请重试";?this.puzzle?=?false;?this.canvasInit();
?}
?};?document.addEventListener("mousemove",?move);?document.addEventListener("mouseup",?up);
}复制代码

4、总结

核心点比较多,写过之后发现不难,关键在于去写

个人该页面git地址:https://github.com/ht-sauce/dream

该页面处于项目的

86aee8687c3b432bb2781457657387eb


路由访问为:http://localhost:8080/consumer

5、完整的页面代码

? ? ?{{?tips?}} ?
?
?
? ? ? ?
?
? ?

最后

喜欢的可以点个关注吗,小可乐也不容易呢

519fce4d340c4ebca62d0a29b0e0346a



猜你喜欢

转载自blog.51cto.com/14516511/2438650
今日推荐