JavaScript模拟实现12306图片验证码

看12306的图片验证码挺好玩的,拿起js我也来实现一个。

既然是验证码就有显示,输入和验证三个过程

1、显示

12306的图片验证码是把一些小图显示在一张大图上,为了实现这个,我去网上找了一些图片,把同一类别的图片放在一个文件夹下面,根据序号依次命名,这个步骤做完就只需要建立索引数组,标记物体名(文件夹以物体名命名)和物体总图片个数,这样子我们就可以从中随记冲去任意一个物体的任意一张图片。

2、输入

输入就是点击图片时会插入的那些笔记小图标啦,对于这些小图标,需要记录下它相对于大图的偏移坐标作为后期验证的依据。

3、验证

验证的过程需要从生成图片的时候就开始了,首先我们会从索引数组中抽取任意张图片(在这里8张)形成一个图片数组,打乱数组的顺序,然后将图片依次画到大图上面去,在这里使用的是canvas,在画小图的过程中,根据显示的偏移量生成验证数组,最后将我们点选图片不同位置时生成的便宜坐标拿过来以此和验证数组进行比对。在这里有一个问题,就是只有点选的坐标数等于验证数组的长度才进行比对,如果长度不一样,那输入肯定是错的。

代码实现:


;(function(){
var Code = (function(){
var canvas,ctx,W,H,picWidth,gap,codeInfo,vCode = [],sources = {};
var init = function(){
W = 293;
H = 190;
var codeContainer = document.createElement("div");
codeContainer.style.cssText=";width:"+W+"px;height:"+H+"px;position:relative;";
codeContainer.id = "codeContainer";
canvas = document.createElement("canvas");
ctx = canvas.getContext("2d");
picWidth = 70;
gap = 3;
canvas.width = W;
canvas.height = H;
codeContainer.appendChild(canvas);
document.body.appendChild(codeContainer);
sources = [
{ "name" : "ant" ,"title" : "蚂蚁" , "count" : 2},
{ "name" : "bee" ,"title" : "蜜蜂" , "count" : 2},
{ "name" : "fan" ,"title" : "电风扇" , "count" : 1},
{ "name" : "flower" ,"title" : "花儿" , "count" : 2},
{ "name" : "hopper" ,"title" : "蚂蚱" , "count" : 2}
];
generateCode();
createRefreshButton();
}
var generateCode = function(){
clear();
codeInfo = getTarget();
var pics = getPics();
drawTitle(codeInfo.title);
particlePics(pics);
}
var createRefreshButton = function(){
var d = document.createElement("div");
d.className = 'refresh';
canvas.parentNode.appendChild(d);
}
var drawTitle = function(name){
var pre = "请点击下图中",middle = "所有的";
ctx.fillStyle = "#000";
ctx.font = "16px Arial";
ctx.fillText(pre,2,16);
ctx.fillStyle = "#f00";
ctx.fillText(middle,textWidth(pre,16)+rand(1,3),16);
ctx.fillStyle = randC();
ctx.font = "20px Arial";
ctx.fillText(name,textWidth(pre+middle,16)+rand(2,5),16);
drawLine();
}
var drawLine = function(){
ctx.beginPath();
ctx.moveTo(0,25);
ctx.lineTo(W,25);
ctx.stroke();
}
var getPics = function(){
var codeCount = Math.round(Math.random()*(codeInfo.count<8?codeInfo.count:8)),itemArr = [],extraArr = [],pics = [];
codeCount = codeCount ? codeCount: codeCount + 1;
var extraCount = 8 - codeCount;
for(var i=0;i<codeInfo.count;i++){
var src = "images/"+ codeInfo.name + "/" + (i+1) +".jpg";
var im  = new Image();
im.src = src;
itemArr.push({
'img' : im,
'name' : codeInfo.name
});
}
while(codeCount>0){
var index = Math.floor(Math.random()*itemArr.length),src = itemArr[index];
pics.push(src);
itemArr.splice(index,1);
codeCount--;
}
for(var index in sources){
var item = sources[index];
if(item.name!=codeInfo.name){
for(var i=0;i<item.count;i++){
var src = "images/"+ item.name + "/" + (i+1) +".jpg";
var im  = new Image();
im.src = src;
extraArr.push({
'img' : im,
'name' : item.name
});
}
}
}
while(extraCount>0){
var index = Math.floor(Math.random()*extraArr.length),src = extraArr[index];
pics.push(src);
extraArr.splice(index,1);
extraCount--;
}
return pics;
}
var particlePics = function(pics){
var pics = randArray(pics);
for(var i=0,l=pics.length;i<l;i++){
(function(i){
var item = pics[i],im = item.img,x = (i%4)*(picWidth+gap),y=((i/4)>>0)*(picWidth+gap)+35;
if(item.name===codeInfo.name){
vCode.push({
'x' : x,
'y' : y
})
}
im.onload = function(){
ctx.drawImage(im,x,y);
}
})(i);
}
}
var verify = function(select,callback){
var len = vCode.length;
callback && callback();
if(select.length!==len){
alert("验证失败!");
reload();
return;
}
var count = 0;
for(var i=0,l=select.length;i<l;i++){
var item = select[i];
vCode.map(function(row){
if(item.x>=row.x&&item.x<=row.x+picWidth&&item.y>=row.y&&item.y<=row.y+picWidth){
count++;
}
})
}
if(count!==len){
alert("验证失败!");
reload();
return;
}else{
alert("验证成功!");
reload();
return;
}
}
var reload = function(){
vCode.length = 0;
generateCode();
}
var clear = function(){
ctx.clearRect(0,0,W,H);
}
var getTarget = function(){
return sources[Math.floor(Math.random()*sources.length)];
}
var textWidth = function(string,size){
ctx.font = size + "px Arial";
return ctx.measureText(string).width;
}
var rand = function(min,max){
return Math.random() * (max - min) + min;
}
var randC = function(){
return "rgb(" + ((Math.random() * 255)>>0) + "," + ((Math.random() * 255)>>0) + "," +((Math.random() * 255)>>0) +")";
}
var randArray = function(arr){
return arr.sort(function(a,b){
return Math.random()>0.5?true:false;
});
}
return {
init : init,
verify : verify,
reload : reload
}
})();
window.Code = window.Code || Code;
})();

在线实例:http://demo.deanhan.cn/12306/

 

  • 支付宝二维码 支付宝
  • 微信二维码 微信

本文地址: /code-12306.html

版权声明: 本文为原创文章,版权归 逐梦个人博客 所有,欢迎分享本文,转载请保留出处!

相关文章