Canvas入门实战之用javascript面向对象实现一个图形验证码

徐小夕 等级 707 0 0

本文主要介绍用canvas实现图形验证码的一些思路以及如何用javascript面向对象的方式更友好的实现canvas的功能,关于canvas的一些基本使用方法和API我整理了一个思维导图,大家感兴趣的可以参考学习。

Canvas入门实战之用javascript面向对象实现一个图形验证码

你将收获

  • 闭包的使用
  • canvas常用api的使用
  • javascript面向对象的实现方式
  • 实现一个canvas的图形验证码的一般思路和常用算法

设计思路

  1. 用canvas生成画布
  2. 用canvas画干扰线或躁点
  3. 生成随机不重复的n的字母
  4. 用canvas绘制文字
  5. 初始化和canvas点击事件
  6. 组件化封装

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

效果预览

Canvas入门实战之用javascript面向对象实现一个图形验证码

实现思路

我将按照上文中的设计思路的步骤一步步实现,首先我们先定义一个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的方式或者更好的方式,欢迎随时和笔者交流。

  1. 用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);
     }
    },

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

  2. 初始化和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
        })
    })();

如果想体验实际案例效果和技术交流,或者感受更多原创canvas,h5游戏demo,可以关注趣谈前端感受哈

更多推荐

收藏
评论区

相关推荐

图形处理:给 Canvas 文本填充线性渐变
在 Canvas 中对文本填充水平或垂直的线性渐变可以轻易实现,而带角度的渐变就复杂很多;就好像下面这样,假设文本矩形宽为 W, 高为 H, 左上角坐标为 X, Y。 渐变示例.jpg(https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/48edf7ce289dab3e1972d973aa
Canvas入门实战之用javascript面向对象实现一个图形验证码
本文主要介绍用canvas实现图形验证码的一些思路以及如何用javascript面向对象的方式更友好的实现canvas的功能,关于canvas的一些基本使用方法和API我整理了一个思维导图,大家感兴趣的可以参考学习。 (https://imghelloworld.osscnbeijing.aliyuncs.com/imgs/b158fad95
GoJS如何制作影像
[GoJS](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.evget.com%2Fproduct%2F3108)是一款功能强大,快速且轻量级的流程图控件,可帮助你在JavaScript 和HTML5 Canvas程序中创建流程图,且极大地简化您的JavaScript / Canv
HTML5 Canvas 学习日志(七)
HTML5 Canvas 学习日志(七) **Export Canvas 导出Canvas** context.fillStyle = "rgb(0, 102, 153)";context.save();context.fillRect(50, 50, 100, 100);context.fillStyle = "rgb(200, 0, 0)"
HTML5实现绘制几何图形
HTML5新增了一个<canvas.../>属性。该元素自身并不绘制图形,只是相当于一张空画布。如果开发者需要向<canvas.../>上绘制图形则必须使用JavaScript脚本进行绘制。 为了向<canvas.../>元素上绘图,必须经过如下3步。 获取<canvas.../>元素对应的DOM对象,这是一个Canvas对象。 调用Canvas对象
Canvas 3D engine_HTML5动画引擎
![Canvas 3D engine_HTML5动画引擎](http://static.oschina.net/uploads/img/201403/22152537_1gkA.jpg) HTML5尚在发展当中,说替代Flash还言之过早,但它所实现的炫目功能大家也是有目共睹的,一个canvas 可以做成如此效果,那我们为什么
Canvas + JavaScript 制作图片粒子效果
学习canvas,javascript的小伙伴,可以跟着我这篇文章的思路一起做一个小效果出来,代码都齐全了。 首先看一下源图和转换成粒子效果的对比图: ![Canvas + JavaScript 制作图片粒子效果](https://oscimg.oschina.net/oscnet/ded02015391ee81719a21ffa584785e84c2.
Canvas和SVG的区别
Canvas和SVG是html5支持的两种可视化技术。基于这两种技术,诞生了很多可视化工具。 Echarts是基于Canvas技术的可视化工具,底层封装了原生的JavaScript的绘图 API。我们很容易联想到另一个同样很优秀的web前端可视化库D3,D3是也最流行的可视化库之一,它被很多其他的表格插件所使用。D3底层基于SVG技术,与Canvas完全不
Canvas:技术小结
Canvas:技术小结 =========== ### 资料 **【教程:MDN官方中文教程】** https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas\_API/Tutorial **【系列博客:每天一点Canvas动画】** https://segmentfault.com/blog/z
GoJS用于HTML图表的JavaScript库
[GoJS](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fwww.evget.com%2Fproduct%2F3108)是一款功能强大,快速且轻量级的流程图控件,可帮助你在JavaScript 和HTML5 Canvas程序中创建流程图,且极大地简化您的JavaScript / Canv
HTML5 & CSS3 初学者指南(4) – Canvas使用
介绍 == 传统的HTML主要用于文本的创建,可以通过<img>标签插入图像,动画的实现则需要第三方插件。在这方面,传统的HTML极其缺乏满足现代网页多媒体需求的能力。HTML5的到来,带来了新的成员<canvas>标签。 什么是 Canvas? =========== HTML5 的 Canvas 元素使用 JavaScript 在网页上绘制图像。
HTML5 Canvas画线技巧
利用Canvas标签换线需要怎么做?首先,我们必须先搭建一个“舞台”。 <!DOCTYPE html>  <html>   <head>    <meta charset="gbk">    <title>Canvas画线技巧</title>   </head>  <body>    <c
HTML5 canvas标签详解
转载: <**canvas**\>是**html5**当中的一个标签,通过Javascript来画图。 <canvas id=”canvas” width=”150″ height=”150″></canvas> <script> var canvas = document.getElementById(”canvas”); var ctx = c
JavaScript强化教程——canvas
本文为 [H5EDU](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.h5edu.cn%2F) 机构官方 [HTML5培训](https://www.oschina.net/action/GoToLink?url=http%3A%2F%2Fwww.h5edu.cn%2F) 教程,主要
Openlayers4中实现动态线效果
**概述:** 本文讲述如何结合canvas在Openlayers4中实现动态线的效果。 **效果:** ![](https://static.oschina.net/uploads/img/201804/25191518_tjv1.jpg) **代码:** 1、move-line扩展 **\[javascript\]** [view plain