JavaScript实现拖动滑块拼图验证功能(html5、canvas)

 更新时间:2021年03月18日 10:09:53   作者:人生行者  
这篇文章主要介绍了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+dHeight
		if(pos.x>this.dx && pos.y>this.dy && pos.x<this.dx+this.dWidth && pos.y<this.dy+this.dHeight ){//表示处于当前图片对象范围内
			return true;
		}
		return false;
	}

方形构造函数

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实现拖动滑块拼图验证内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS正则子匹配实例分析

    JS正则子匹配实例分析

    这篇文章主要介绍了JS正则子匹配用法,结合简单实例形式分析了js正则字匹配的概念、用法与相关注意事项,需要的朋友可以参考下
    2016-12-12
  • js Dialog 去掉右上角的X关闭功能

    js Dialog 去掉右上角的X关闭功能

    用到 dialog弹出框时,不想要右上角的X 关闭功能,只是做个提示信息显示,下面是具体的去掉方法,大家可以参考下
    2014-04-04
  • javascript显示动态时间的方法汇总

    javascript显示动态时间的方法汇总

    本文给大家汇总介绍了3种javascript实现动态显示时间的方法及详细示例,有需要的小伙伴可以参考下
    2018-07-07
  • 浅谈键盘上回车按钮的js触发事件

    浅谈键盘上回车按钮的js触发事件

    下面小编就为大家带来一篇浅谈键盘上回车按钮的js触发事件。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • 小程序ios音频播放没声音问题的解决

    小程序ios音频播放没声音问题的解决

    这篇文章主要介绍了小程序ios音频播放没声音问题的解决,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • js获取时间(本周、本季度、本月..)

    js获取时间(本周、本季度、本月..)

    js获取时间,包括:获取本周、本季度、本月、上月的开端日期、停止日期,下面有个不错的示例,感兴趣的朋友可以参考下
    2013-11-11
  • javascript中返回顶部按钮的实现

    javascript中返回顶部按钮的实现

    这篇文章主要介绍了使用javascript实现博客园页面右下角返回顶部按钮的思路及源码,非常不错,这里推荐给小伙伴们
    2015-05-05
  • JS获取本地地址及天气的方法实例小结

    JS获取本地地址及天气的方法实例小结

    这篇文章主要介绍了JS获取本地地址及天气的方法,结合实例形式总结分析了javascript通过浏览器、第三方API实现获取本地地址与天气的相关操作技巧,需要的朋友可以参考下
    2019-05-05
  • 微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现

    微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现

    这篇文章主要介绍了微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • JS 树形递归实例代码

    JS 树形递归实例代码

    下面的代码是从实际项目中AJAX的回调部分 copy 出来的,使用了JS的递归,文本格式为JSON
    2010-05-05

最新评论