• 纯JS打造12306验证码功能
  • 黑色平底锅 发表于 2016/3/18 19:01:00 | 分类标签: 验证码 12306验证码
  •  没事瞎折腾,模拟一个12306验证码。实现如下:
    code.js内容:
    ;(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;
    })();
    demo页代码:
    <!DOCTYPE html>
    <html lang="en">
    <head>
            <meta charset="UTF-8">
            <title>模拟12306验证码</title>
            <style type="text/css">
                    .marker{
                            position: absolute;
                            width: 26px;
                            height: 26px;
                            background: url(images/marker.png) no-repeat;
                    }
                    .refresh{
                            width: 53px;
                            height: 22px;
                            right: 3px;
                            top: 0;
                            cursor: pointer;
                            position: absolute;
                            background: url(images/refresh.png) no-repeat;
                    }
            </style>
    </head>
    <body>
            <button class="verify">验证</button>
            <script type="text/javascript" src="js/code.js"></script>
            <script type="text/javascript" src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
            <script type="text/javascript">
                    $(document).ready(function() {
                            Code.init();
                            $(document).on("click","#codeContainer canvas",function(event){
                                    createInput(convertPoint($(this),event.pageX,event.pageY));
                                    createMarker(event.pageX,event.pageY);
                            })
                            $(".verify").on("click",function(){
                                    var code = [];
                                    $(".code-value").each(function(){
                                            code.push(JSON.parse($(this).val()));
                                    });
                                    Code.verify(code,reset);
                            });
                            $(".refresh").on("click",function(){
                                    Code.reload();
                                     reset();
                            })
                            function createInput(point){
                                    $("<input />").attr({
                                            value: JSON.stringify(point),
                                            class: 'code-value'
                                    }).appendTo("body").hide();
                            }
                            function reset(){
                                    $(".code-value").remove();
                                    $(".marker").remove();
                            }
                            function createMarker(x,y){
                                    $("<div />").attr({
                                            class : 'marker',
                                    }).css({
                                            left : x - 13,
                                            top : y - 13
                                    }).appendTo('body');
                            }
                            function convertPoint(elem,x,y){
                                    var offset = elem.offset();
                                    return {
                                            x : x - offset.left,
                                            y : y - offset.top
                                    }
                            }
                    });
            </script>
    </body>
    </html>
    效果图:
  • 请您注意

    ·自觉遵守:爱国、守法、自律、真实、文明的原则

    ·尊重网上道德,遵守《全国人大常委会关于维护互联网安全的决定》及中华人民共和国其他各项有关法律法规

    ·严禁发表危害国家安全,破坏民族团结、国家宗教政策和社会稳定,含侮辱、诽谤、教唆、淫秽等内容的作品

    ·承担一切因您的行为而直接或间接导致的民事或刑事法律责任

    ·您在编程中国社区新闻评论发表的作品,本网站有权在网站内保留、转载、引用或者删除

    ·参与本评论即表明您已经阅读并接受上述条款

  • 感谢本文作者
  • 作者头像
  • 昵称:黑色平底锅
  • 加入时间:2013/6/13 0:00:00
  • TA的签名
  • 这家伙很懒,虾米都没写
  • +进入TA的空间
  • 以下内容也很赞哦
分享按钮