JavaScript realizes dragging slider puzzle verification (html5, canvas)

Introduction: Slider drag verification is now used in many places. I thought about writing one over the weekend and put it up to see if anyone can use it!

effect:

Realization ideas:

  1. Use a canvas to draw the source image, and then draw a filled square, so that the missing effect can be achieved (the coordinates of the square are random);
  2. Use another canvas to draw the dragging block, and use drawImage to capture the original image with the same coordinates and size as the square area in the previous step, as the verification image, and place the verification image on the far left;
  3. At the drag block, press the mouse and then drag, the drag block and the verification diagram will move with the mouse, and after reaching a certain range, release the mouse to verify;
  4. If the verification is passed, it will prompt that the verification is successful. If the verification is not passed, the drag block and the verification diagram will return to the far left.

 

3 constructors

Picture constructor

//图片对象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;
	}

Square constructor

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;
	}

Text constructor

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;
	}

Draw source graphs and missing blocks

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);

At this time, the page effect is as follows

Draw verification diagram and drag block

Note: The drawing coordinates of the verification map are the same as the coordinates of the missing blocks drawn in the previous step.

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);

Effect picture:

Canvas 2 add event

//给canvas画布添加点击事件
canvas2.addEventListener('mousedown',this.mouseDown.bind(this));
canvas2.addEventListener('mouseup',this.mouseUp.bind(this));
canvas2.addEventListener('mousemove',this.mouseMove.bind(this));

Mouse down event

  1. Record the x coordinate when the mouse is pressed, and keep the mouse moving.
  2. Change the movement flag to true to prevent the effect of movement without dragging the slider.
	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;//记录鼠标按下的位置,保持移动
			}
	}

Mouse movement event

  1. The initial X coordinate of the mouse click needs to be subtracted when the verification graph and the slider move.
  2. When it exceeds a certain range, it cannot be moved to prevent it from moving out of the canvas range.
	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();
	}

Mouse release event

  1. The move mark of the mouse is false;
  2. If you release the mouse when the verification range is not reached, the slider and verification diagram will return to the far left;
  3. When the movement of the verification map reaches a certain range, it means that the verification is passed;
  4. After the verification is passed, it is prompted that the verification is passed, and the relevant content needs to be changed, such as the removal of missing blocks, the change of the prompt text content, etc.;
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="验证成功";
	}

After success as follows:

 

Complete code download, no points required

To the three brothers!

 

Guess you like

Origin blog.csdn.net/dkm123456/article/details/114821927