JavaScript實(shí)現(xiàn)拖動(dòng)滑塊拼圖驗(yàn)證功能(html5、canvas)
引言:
滑塊拖動(dòng)驗(yàn)證現(xiàn)在很多地方都用到,周末就琢磨著寫了一個(gè),放上來,看看有沒有人用得上! 效果:
實(shí)現(xiàn)思路:
用一張畫布繪制源圖,再繪制一個(gè)填充的方形,這樣就可以達(dá)到缺失的效果(方形的坐標(biāo)是隨機(jī)的);
再用一個(gè)畫布繪制拖動(dòng)塊,同時(shí)用drawImage截取和上一步中方形區(qū)域一樣坐標(biāo)、大小的原圖,就作為驗(yàn)證圖了,把驗(yàn)證圖放在最左邊;
在拖動(dòng)塊處,按下鼠標(biāo)然后拖動(dòng),拖動(dòng)塊和驗(yàn)證圖會跟隨鼠標(biāo)移動(dòng),達(dá)到一定范圍后放開鼠標(biāo),會進(jìn)行驗(yàn)證;
驗(yàn)證通過則提示驗(yàn)證成功,驗(yàn)證不通過則拖動(dòng)塊和驗(yàn)證圖會返回到最左邊。
3個(gè)構(gòu)造函數(shù) 圖片構(gòu)造函數(shù)
//圖片對象ImageDraw構(gòu)造函數(shù) function ImageDraw(o,obj){ this.id='', this.image=0,//圖片對象(必填) this.sx=0,//圖片切片開始x位置(顯示整個(gè)圖片的時(shí)候不需要填) this.sy=0,//圖片切片開始y位置(顯示整個(gè)圖片的時(shí)候不需要填) this.sWidth=0, //圖片切片開始寬度(顯示整個(gè)圖片的時(shí)候不需要填) this.sHeight=0,//圖片切片開始高度(顯示整個(gè)圖片的時(shí)候不需要填) this.dx=0, //圖片目標(biāo)x位置(必填) this.dy=0, //圖片目標(biāo)y位置(必填) this.dWidth=0,//圖片目標(biāo)顯示寬度(寬度不縮放時(shí)不必填) this.dHeight=0//圖片目標(biāo)高度高度(高度不縮放時(shí)不必填) 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("繪制圖片缺失參數(shù)"); return; } ctx.translate(obj.dx,obj.dy); if(getType(obj.sx)!='undefined' && getType(obj.sy)!='undefined' && obj.sWidth && obj.sHeight && obj.dWidth && obj.dHeight){ //裁剪圖片,顯示時(shí)候有縮放 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);//原始圖片,顯示時(shí)候有縮放 }else{ ctx.drawImage(obj.image,0, 0);//原始圖片,顯示時(shí)候無縮放 } ctx.restore(); } } ImageDraw.prototype.isPoint=function(pos){ //鼠標(biāo)位置的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 ){//表示處于當(dāng)前圖片對象范圍內(nèi) return true; } return false; }
方形構(gòu)造函數(shù)
function Rect(o){ this.x=0,//x坐標(biāo) this.y=0,//y坐標(biāo) this.width=100,//寬 this.height=40,//高 this.thin=true,//線段薄一點(diǎn) 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; }
文本構(gòu)造函數(shù)
function Text(o){ this.x=0,//x坐標(biāo) this.y=0,//y坐標(biāo) this.text='',//內(nèi)容 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); //繪制驗(yàn)證塊長條 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:'拖動(dòng)滑塊驗(yàn)證', font:'18px serif', textAlign:'center', fill:true, //fillStyle:'white' }); this.renderArr.push(text);
此時(shí)頁面效果如下
繪制驗(yàn)證圖和拖動(dòng)塊
注意:驗(yàn)證圖的繪制坐標(biāo)與上一步繪制缺失塊的坐標(biāo)是一樣的。
var pos = this.validPos;//上一步繪制缺失塊的坐標(biāo),驗(yàn)證圖需根據(jù)這個(gè)坐標(biāo)來截取 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畫布添加點(diǎn)擊事件 canvas2.addEventListener('mousedown',this.mouseDown.bind(this)); canvas2.addEventListener('mouseup',this.mouseUp.bind(this)); canvas2.addEventListener('mousemove',this.mouseMove.bind(this));
鼠標(biāo)按下事件
- 記錄鼠標(biāo)按下時(shí)的x坐標(biāo),保持鼠標(biāo)移動(dòng)不飄。
- 改變移動(dòng)標(biāo)記為true,防止沒有拖動(dòng)滑塊而產(chǎn)生移動(dòng)的效果。
Slider.prototype.mouseDown=function(e){ var pos = _.getOffset(e);//獲取鼠標(biāo)位置 if(!this.block) return ; if(this.block.isPoint(pos)){//按下的位置是滑塊的位置 this.move=true;//表示可以移動(dòng) this.downX=pos.x;//記錄鼠標(biāo)按下的位置,保持移動(dòng) } }
鼠標(biāo)移動(dòng)事件
- 驗(yàn)證圖和滑塊移動(dòng)時(shí)需減去鼠標(biāo)點(diǎn)擊的初始X坐標(biāo)。
- 當(dāng)超過一定范圍則不能再移動(dòng),防止移出畫布范圍。
Slider.prototype.mouseMove=function(e){ if(!this.move) return ;//移動(dòng)標(biāo)記為false則直接返回 var pos = _.getOffset(e); pos.x -= this.downX;//要減去鼠標(biāo)初始點(diǎn)擊的位置 if(pos.x>580){ return ; } this.update(pos);//移動(dòng) } //更新 Slider.prototype.update=function(pos){ //更改滑塊和驗(yàn)證圖的坐標(biāo) _.each(this.renderArr2,function(item){ if(item){ item.dx=pos.x; } }); //繪制 this.render(); }
鼠標(biāo)放開事件
- 鼠標(biāo)移動(dòng)move標(biāo)記為false;
- 未達(dá)到驗(yàn)證范圍而放開鼠標(biāo),滑塊和驗(yàn)證圖會回到最左邊;
- 當(dāng)驗(yàn)證圖的移動(dòng)達(dá)到一定范圍,則表示驗(yàn)證通過;
驗(yàn)證通過后,提示驗(yàn)證通過,相關(guān)內(nèi)容要做出改變,比如缺失塊的清除、提示文字內(nèi)容的改變等;
Slider.prototype.mouseUp=function(e){ this.move=false; var pos = _.getOffset(e); pos.x -= this.downX; var validPos = this.validPos;//驗(yàn)證快的坐標(biāo) if(Math.abs(pos.x-validPos.x )<=10){//驗(yàn)證通過(x位置的差值多少范圍內(nèi)即可) console.log('通過') this.suc(); }else{//驗(yàn)證不通過 this.update({x:0}); } this.render(); } Slider.prototype.suc=function(){ this.renderArr.splice(2,1);//清楚缺失塊 this.block=null; //滑塊和驗(yàn)證圖的清除 this.renderArr2.length=0; //長條顏色的改變 this.renderArr[1].fillStyle='#78C430'; var text = this.renderArr[2]; //提示內(nèi)容的改變 text.fillStyle='white'; text.text="驗(yàn)證成功"; }
成功后如下:
到此這篇關(guān)于JavaScript實(shí)現(xiàn)拖動(dòng)滑塊拼圖驗(yàn)證(html5、canvas)的文章就介紹到這了,更多相關(guān)js實(shí)現(xiàn)拖動(dòng)滑塊拼圖驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js 計(jì)數(shù)排序的實(shí)現(xiàn)示例(升級版)
這篇文章主要介紹了js 計(jì)數(shù)排序的實(shí)現(xiàn)示例(升級版),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-01-01javascript實(shí)現(xiàn)通過表格繪制顏色填充矩形的方法
這篇文章主要介紹了javascript實(shí)現(xiàn)通過表格繪制顏色填充矩形的方法,涉及javascript操作表格與樣式的相關(guān)技巧,需要的朋友可以參考下2015-04-04原生JavaScript+LESS實(shí)現(xiàn)瀑布流
這篇文章主要介紹了原生JavaScript+LESS實(shí)現(xiàn)瀑布流的方法,附上了具體實(shí)例,這里推薦給有需要的小伙伴。2014-12-12Javascript 類的繼承實(shí)現(xiàn)代碼
JavaScript中類的學(xué)習(xí),從基本類繼承過來方法。2009-07-07