JavaScript实现拖动滑块拼图验证功能(html5、canvas)
引言:
滑块拖动验证现在很多地方都用到,周末就琢磨着写了一个,放上来,看看有没有人用得上! 效果:
【JavaScript实现拖动滑块拼图验证功能(html5、canvas)】
文章图片
实现思路:
用一张画布绘制源图,再绘制一个填充的方形,这样就可以达到缺失的效果(方形的坐标是随机的);
再用一个画布绘制拖动块,同时用drawImage截取和上一步中方形区域一样坐标、大小的原图,就作为验证图了,把验证图放在最左边;
在拖动块处,按下鼠标然后拖动,拖动块和验证图会跟随鼠标移动,达到一定范围后放开鼠标,会进行验证;
验证通过则提示验证成功,验证不通过则拖动块和验证图会返回到最左边。
3个构造函数 图片构造函数
//图片对象ImageDraw构造函数 function ImageDraw(o,obj){this.id='',this.image=0,//图片对象(必填)this.sx=0,//图片切片开始x位置(显示整个图片的时候不需要填)this.sy=0,//图片切片开始y位置(显示整个图片的时候不需要填)this.sWidth=0, //图片切片开始宽度(显示整个图片的时候不需要填)this.sHeight=0,//图片切片开始高度(显示整个图片的时候不需要填)this.dx=0, //图片目标x位置(必填)this.dy=0, //图片目标y位置(必填)this.dWidth=0,//图片目标显示宽度(宽度不缩放时不必填)this.dHeight=0//图片目标高度高度(高度不缩放时不必填)this.init(o,obj); } ImageDraw.prototype.init=function(o,obj){for(var key in o){this[key]=o[key]; }return this; } ImageDraw.prototype.render=function(context){draw(context,this); function draw(context,obj) {var ctx=context; ctx.save(); if(!obj.image || getType(obj.dx)=='undefined' || getType(obj.dy)=='undefined'){throw new Error("绘制图片缺失参数"); return; } ctx.translate(obj.dx,obj.dy); if(getType(obj.sx)!='undefined' && getType(obj.sy)!='undefined' && obj.sWidth && obj.sHeight && obj.dWidth && obj.dHeight){//裁剪图片,显示时候有缩放ctx.drawImage(obj.image, obj.sx, obj.sy, obj.sWidth, obj.sHeight, 0, 0, obj.dWidth, obj.dHeight); }else if(obj.dWidth && obj.dHeight){ctx.drawImage(obj.image, 0, 0, obj.dWidth, obj.dHeight); //原始图片,显示时候有缩放}else{ctx.drawImage(obj.image,0, 0); //原始图片,显示时候无缩放}ctx.restore(); } } ImageDraw.prototype.isPoint=function(pos){//鼠标位置的x、y要分别大于dx、dy 且x、y要分别小于 dx+dWidth、dy+dHeightif(pos.x>this.dx && pos.y>this.dy && pos.x
方形构造函数
function Rect(o){this.x=0,//x坐标this.y=0,//y坐标this.width=100,//宽this.height=40,//高this.thin=true,//线段薄一点this.init(o); } Rect.prototype.init=function(o){for(var key in o){this[key]=o[key]; } } Rect.prototype.render=function(context){this.ctx=context; innerRender(this); function innerRender(obj){var ctx=obj.ctx; ctx.save()ctx.beginPath(); ctx.translate(obj.x,obj.y); if(obj.lineWidth){ctx.lineWidth=obj.lineWidth; }if(obj.thin){ctx.translate(0.5,0.5); }ctx.rect(0,0,obj.width,obj.height); if(obj.fill){//是否填充obj.fillStyle?(ctx.fillStyle=obj.fillStyle):null; ctx.fill(); }if(obj.stroke){//是否描边obj.strokeStyle?(ctx.strokeStyle=obj.strokeStyle):null; ctx.stroke(); } ctx.restore(); }return this; }
文本构造函数
function Text(o){this.x=0,//x坐标this.y=0,//y坐标this.text='',//内容this.font=null; //字体this.textAlign=null; //对齐方式this.init(o); } Text.prototype.init=function(o){for(var key in o){this[key]=o[key]; } } Text.prototype.render=function(context){this.ctx=context; innerRender(this); function innerRender(obj){var ctx=obj.ctx; ctx.save()ctx.beginPath(); ctx.translate(obj.x,obj.y); if(obj.font){ctx.font=obj.font; }if(obj.textAlign){ctx.textAlign=obj.textAlign; }if(obj.fill){//是否填充obj.fillStyle?(ctx.fillStyle=obj.fillStyle):null; ctx.fillText(obj.text,0,0); }ctx.restore(); }return this; }
绘制源图和缺失块
var img = new ImageDraw({image:this.imgObj[0],dx:0, dy:0 ,dWidth:640,dHeight:360},this); this.renderArr.push(img); var x=_.getRandom(100,580); //x从100-580之间取var y=_.getRandom(0,300); //y从0-300之间取this.validPos={x:x,y:y}; //缺失块绘制var rect = new Rect({x:x,y:y,width:60,height:60,fill:true,fillStyle:'gray'})this.renderArr.push(rect); //绘制验证块长条var rect = new Rect({x:0,y:360,width:640,height:40,fill:true,fillStyle:'#E8E8E8'})this.renderArr.push(rect); //绘制文字var text = new Text({x:300,y:390,text:'拖动滑块验证',font:'18px serif',textAlign:'center',fill:true,//fillStyle:'white'}); this.renderArr.push(text);
此时页面效果如下
![]()
文章图片
绘制验证图和拖动块 注意:验证图的绘制坐标与上一步绘制缺失块的坐标是一样的。
var pos = this.validPos; //上一步绘制缺失块的坐标,验证图需根据这个坐标来截取var img = new ImageDraw({image:this.imgObj[0],sx:pos.x,sy:pos.y,sWidth:60,sHeight:60,dx:0, dy:pos.y,dWidth:60,dHeight:60},this); this.renderArr2.push(img); var img1 = new ImageDraw({image:this.imgObj[1],dx:0, dy:360 ,dWidth:40,dHeight:40},this); this.renderArr2.push(img1);
效果图:
![]()
文章图片
画布2添加事件
//给canvas画布添加点击事件canvas2.addEventListener('mousedown',this.mouseDown.bind(this)); canvas2.addEventListener('mouseup',this.mouseUp.bind(this)); canvas2.addEventListener('mousemove',this.mouseMove.bind(this));
鼠标按下事件
- 记录鼠标按下时的x坐标,保持鼠标移动不飘。
- 改变移动标记为true,防止没有拖动滑块而产生移动的效果。
Slider.prototype.mouseDown=function(e){var pos = _.getOffset(e); //获取鼠标位置if(!this.block) return ; if(this.block.isPoint(pos)){//按下的位置是滑块的位置this.move=true; //表示可以移动this.downX=pos.x; //记录鼠标按下的位置,保持移动} }
鼠标移动事件
- 验证图和滑块移动时需减去鼠标点击的初始X坐标。
- 当超过一定范围则不能再移动,防止移出画布范围。
Slider.prototype.mouseMove=function(e){if(!this.move) return ; //移动标记为false则直接返回var pos = _.getOffset(e); pos.x -= this.downX; //要减去鼠标初始点击的位置if(pos.x>580){return ; }this.update(pos); //移动 } //更新 Slider.prototype.update=function(pos){//更改滑块和验证图的坐标_.each(this.renderArr2,function(item){if(item){item.dx=pos.x; }}); //绘制this.render(); }
鼠标放开事件
验证通过后,提示验证通过,相关内容要做出改变,比如缺失块的清除、提示文字内容的改变等;
- 鼠标移动move标记为false;
- 未达到验证范围而放开鼠标,滑块和验证图会回到最左边;
- 当验证图的移动达到一定范围,则表示验证通过;
Slider.prototype.mouseUp=function(e){this.move=false; var pos = _.getOffset(e); pos.x -= this.downX; var validPos = this.validPos; //验证快的坐标if(Math.abs(pos.x-validPos.x )<=10){//验证通过(x位置的差值多少范围内即可)console.log('通过')this.suc(); }else{//验证不通过this.update({x:0}); }this.render(); } Slider.prototype.suc=function(){this.renderArr.splice(2,1); //清楚缺失块this.block=null; //滑块和验证图的清除this.renderArr2.length=0; //长条颜色的改变this.renderArr[1].fillStyle='#78C430'; var text = this.renderArr[2]; //提示内容的改变text.fillStyle='white'; text.text="验证成功"; }
成功后如下:
![]()
文章图片
完整代码下载
到此这篇关于JavaScript实现拖动滑块拼图验证(html5、canvas)的文章就介绍到这了,更多相关js实现拖动滑块拼图验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 事件代理
- 孩子不是实现父母欲望的工具——林哈夫
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- java中如何实现重建二叉树
- 数组常用方法一
- 人脸识别|【人脸识别系列】| 实现自动化妆