web前端开发学习——Canvas入门实战之实现一个图形验证码
小职 2020-12-21 来源 :趣谈前端 阅读 735 评论 0

摘要:本篇主要介绍了用canvas实现图形验证码的思路,通过本篇的学习你可以收获闭包的使用,canvas常用api的使用,javascript面向对象的实现方式,实现一个canvas的图形验证码的一般思路和常用算法。

本篇主要介绍了用canvas实现图形验证码的思路,通过本篇的学习你可以收获闭包的使用,canvas常用api的使用,javascript面向对象的实现方式,实现一个canvas的图形验证码的一般思路和常用算法。

web前端开发学习——Canvas入门实战之实现一个图形验证码 

 

设计思路

 

用canvas生成画布

用canvas画干扰线或躁点

生成随机不重复的n的字母

用canvas绘制文字

初始化和canvas点击事件

组件化封装

文末将附上组件封装的源码,欢迎大家随时沟通交流。关于项目的打包,我将使用自己基于gulp4搭建的9012教你如何使用gulp4开发项目脚手架。

 

效果预览

 web前端开发学习——Canvas入门实战之实现一个图形验证码


 

我将按照上文中的设计思路的步骤一步步实现,首先我们先定义一个es5类:

 

function Gcode(el, option) {

    this.el = typeof el === 'string' ? document.querySelector(el) : el;

    this.option = option;

    this.init();

}

其中init是用来初始化用的,参数el代表需要挂载的元素或元素id,option为传入的可选项,稍后会在代码中体现,通常这也是面向对象的常用套路。

 

1.绘制画布

 

Gcode.prototype = {

    constructor: Gcode,

    init: function() {

        if(this.el.getContext) {

            isSupportCanvas = true;

            var ctx = this.el.getContext('2d'),

            // 设置画布宽高

            cw = this.el.width = this.option.width || 200,

            ch = this.el.height = this.option.height || 40;

        }

    }

}

这里我们在初始化方法中先定义一个canvas画布,宽高为用户自定义的宽高,默认为200*40。

 

2.绘制干扰线

 

// 画干扰线

drawLine: function(ctx, lineNum, maxW, maxH) {

    ctx.clearRect(0, 0, maxW, maxH);

    for(var i=0; i < lineNum; i++) {

        var dx1 = Math.random()* maxW,

            dy1 = Math.random()* maxH,

            dx2 = Math.random()* maxW,

            dy2 = Math.random()* maxH;

        ctx.strokeStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';

        ctx.beginPath();

        ctx.moveTo(dx1, dy1);

        ctx.lineTo(dx2, dy2);

        ctx.stroke();

    }

}

这里我们对类Gcode定义原型方法drawLine,然后通过for循环绘制随机位置的线条,为了让canvas每次点击能清空之前的干扰线,我们使用clearRect来清除画布。

 

3.生成随机不重复的n个字符

 

我们通过递归实现,如下==:

 

// 生成唯一文字

generateUniqueText: function(source, hasList, limit) {

    var text = source[Math.floor(Math.random()*limit)];

    if(hasList.indexOf(text) > -1) {

        return this.generateUniqueText(source, hasList, limit)

    }else {

        return text

    }   

}

// 生成指定个数的随机文字

randomText: function(len) {

    var source = ['a', 'b', 'c', 'd', 'e',

    'f', 'g', 'h', 'i', 'j',  

    'k', 'l', 'm', 'o', 'p',

    'q', 'r', 's', 't', 'u',

    'v', 'w', 'x', 'y', 'z'];

    var result = [];

    var sourceLen = source.length;

    for(var i=0; i< len; i++) {

        var text = this.generateUniqueText(source, result, sourceLen);

        result.push(text)

    }

    return result.join('')

}

我们通过定义一个字母表,传入生成的随机字母的个数,配合generateUniqueText来实现生成唯一不重复的n个随机字符。当然笔者认为这个方法并不优雅,你也可以使用uuid的方式或者更好的方式,欢迎随时和笔者交流。

 

4.用canvas绘制文字

 

// 画文字

drawText: function(ctx, text, maxH) {

    var len = text.length;

    for(var i=0; i < len; i++) {

        var dx = 30 * Math.random() + 30* i,

            dy = Math.random()* 5 + maxH/2;

        ctx.fillStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';

        ctx.font = '30px Helvetica';

        ctx.textBaseline = 'middle';

        ctx.fillText(text[i], dx, dy);

    }

},

这里和上文画线实现类似。就不做过多介绍了。

 

5.初始化和canvas点击事件

 

接下来我们看看完整的初始化代码:

 

init: function() {

    if(this.el.getContext) {

        isSupportCanvas = true;

        var ctx = this.el.getContext('2d'),

        // 设置画布宽高

        cw = this.el.width = this.option.width || 200,

        ch = this.el.height = this.option.height || 40,

        textLen = this.option.textLen || 4,

        lineNum = this.option.lineNum || 4;

        var text = this.randomText(textLen);

 

        this.onClick(ctx, textLen, lineNum, cw, ch);

        this.drawLine(ctx, lineNum, cw, ch);

        this.drawText(ctx, text, ch);

    }

}

点击事件主要是为了用户点击可以切换验证码:

 

onClick: function(ctx, textLen, lineNum, cw, ch) {

    var _ = this;

    this.el.addEventListener('click', function(){

        text = _.randomText(textLen);

        _.drawLine(ctx, lineNum, cw, ch);

        _.drawText(ctx, text, ch);

    }, false)

}

到此,一个完整的验证码组件实现完成,怎么用呢?如下:

 

new Gcode('#canvas_code', {

        lineNum: 6,  // 可选

        textLen: 4,  // 可选

        width: 200,  // 可选

        height: 50   // 可选

    })

完整代码如下,欢迎学习交流:

 

// canvas绘制图形验证码

    (function(){

        function Gcode(el, option) {

            this.el = typeof el === 'string' ? document.querySelector(el) : el;

            this.option = option;

            this.init();

        }

        Gcode.prototype = {

            constructor: Gcode,

            init: function() {

                if(this.el.getContext) {

                    isSupportCanvas = true;

                    var ctx = this.el.getContext('2d'),

                    // 设置画布宽高

                    cw = this.el.width = this.option.width || 200,

                    ch = this.el.height = this.option.height || 40,

                    textLen = this.option.textLen || 4,

                    lineNum = this.option.lineNum || 4;

                    var text = this.randomText(textLen);

         

                    this.onClick(ctx, textLen, lineNum, cw, ch);

                    this.drawLine(ctx, lineNum, cw, ch);

                    this.drawText(ctx, text, ch);

                }

            },

            onClick: function(ctx, textLen, lineNum, cw, ch) {

                var _ = this;

                this.el.addEventListener('click', function(){

                    text = _.randomText(textLen);

                    _.drawLine(ctx, lineNum, cw, ch);

                    _.drawText(ctx, text, ch);

                }, false)

            },

            // 画干扰线

            drawLine: function(ctx, lineNum, maxW, maxH) {

                ctx.clearRect(0, 0, maxW, maxH);

                for(var i=0; i < lineNum; i++) {

                    var dx1 = Math.random()* maxW,

                        dy1 = Math.random()* maxH,

                        dx2 = Math.random()* maxW,

                        dy2 = Math.random()* maxH;

                    ctx.strokeStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';

                    ctx.beginPath();

                    ctx.moveTo(dx1, dy1);

                    ctx.lineTo(dx2, dy2);

                    ctx.stroke();

                }

            },

            // 画文字

            drawText: function(ctx, text, maxH) {

                var len = text.length;

                for(var i=0; i < len; i++) {

                    var dx = 30 * Math.random() + 30* i,

                        dy = Math.random()* 5 + maxH/2;

                    ctx.fillStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';

                    ctx.font = '30px Helvetica';

                    ctx.textBaseline = 'middle';

                    ctx.fillText(text[i], dx, dy);

                }

            },

            // 生成指定个数的随机文字

            randomText: function(len) {

                var source = ['a', 'b', 'c', 'd', 'e',

                'f', 'g', 'h', 'i', 'j',  

                'k', 'l', 'm', 'o', 'p',

                'q', 'r', 's', 't', 'u',

                'v', 'w', 'x', 'y', 'z'];

                var result = [];

                var sourceLen = source.length;

                for(var i=0; i< len; i++) {

                    var text = this.generateUniqueText(source, result, sourceLen);

                    result.push(text)

                }

                return result.join('')

            },

            // 生成唯一文字

            generateUniqueText: function(source, hasList, limit) {

                var text = source[Math.floor(Math.random()*limit)];

                if(hasList.indexOf(text) > -1) {

                    return this.generateUniqueText(source, hasList, limit)

                }else {

                    return text

                }   

            }

        }

        new Gcode('#canvas_code', {

            lineNum: 6

        })

    })(); 



关注“职坐标在线”(Zhizuobiao_Online)公众号,免费获取学习视频资料、技术就业咨询。

web前端开发学习——Canvas入门实战之实现一个图形验证码

本文由 @小职 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程