Canvas入门实战之实现一个图形验证码

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

成都创新互联是一家集网站建设,西夏企业网站建设,西夏品牌网站建设,网站定制,西夏网站建设报价,网络营销,网络优化,西夏网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

 

你将收获

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

设计思路

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

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

效果预览

实现思路

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

 
 
 
 
  1. function Gcode(el, option) {
  2.     this.el = typeof el === 'string' ? document.querySelector(el) : el;
  3.     this.option = option;
  4.     this.init();
  5. }

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

1.绘制画布

 
 
 
 
  1. Gcode.prototype = {
  2.     constructor: Gcode,
  3.     init: function() {
  4.         if(this.el.getContext) {
  5.             isSupportCanvas = true;
  6.             var ctx = this.el.getContext('2d'),
  7.             // 设置画布宽高
  8.             cw = this.el.width = this.option.width || 200,
  9.             ch = this.el.height = this.option.height || 40;
  10.         }
  11.     }
  12. }

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

2.绘制干扰线

 
 
 
 
  1. // 画干扰线
  2. drawLine: function(ctx, lineNum, maxW, maxH) {
  3.     ctx.clearRect(0, 0, maxW, maxH);
  4.     for(var i=0; i < lineNum; i++) {
  5.         var dx1 = Math.random()* maxW,
  6.             dy1 = Math.random()* maxH,
  7.             dx2 = Math.random()* maxW,
  8.             dy2 = Math.random()* maxH;
  9.         ctx.strokeStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';
  10.         ctx.beginPath();
  11.         ctx.moveTo(dx1, dy1);
  12.         ctx.lineTo(dx2, dy2);
  13.         ctx.stroke();
  14.     }
  15. }

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

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

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

 
 
 
 
  1. // 生成唯一文字
  2. generateUniqueText: function(source, hasList, limit) {
  3.     var text = source[Math.floor(Math.random()*limit)];
  4.     if(hasList.indexOf(text) > -1) {
  5.         return this.generateUniqueText(source, hasList, limit)
  6.     }else {
  7.         return text
  8.     }  
  9. }
  10. // 生成指定个数的随机文字
  11. randomText: function(len) {
  12.     var source = ['a', 'b', 'c', 'd', 'e',
  13.     'f', 'g', 'h', 'i', 'j', 
  14.     'k', 'l', 'm', 'o', 'p',
  15.     'q', 'r', 's', 't', 'u',
  16.     'v', 'w', 'x', 'y', 'z'];
  17.     var result = [];
  18.     var sourceLen = source.length;
  19.     for(var i=0; i< len; i++) {
  20.         var text = this.generateUniqueText(source, result, sourceLen);
  21.         result.push(text)
  22.     }
  23.     return result.join('')
  24. }

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

4.用canvas绘制文字

 
 
 
 
  1. // 画文字
  2. drawText: function(ctx, text, maxH) {
  3.     var len = text.length;
  4.     for(var i=0; i < len; i++) {
  5.         var dx = 30 * Math.random() + 30* i,
  6.             dy = Math.random()* 5 + maxH/2;
  7.         ctx.fillStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';
  8.         ctx.font = '30px Helvetica';
  9.         ctx.textBaseline = 'middle';
  10.         ctx.fillText(text[i], dx, dy);
  11.     }
  12. },

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

5.初始化和canvas点击事件

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

 
 
 
 
  1. init: function() {
  2.     if(this.el.getContext) {
  3.         isSupportCanvas = true;
  4.         var ctx = this.el.getContext('2d'),
  5.         // 设置画布宽高
  6.         cw = this.el.width = this.option.width || 200,
  7.         ch = this.el.height = this.option.height || 40,
  8.         textLen = this.option.textLen || 4,
  9.         lineNum = this.option.lineNum || 4;
  10.         var text = this.randomText(textLen);
  11.         this.onClick(ctx, textLen, lineNum, cw, ch);
  12.         this.drawLine(ctx, lineNum, cw, ch);
  13.         this.drawText(ctx, text, ch);
  14.     }
  15. }

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

 
 
 
 
  1. onClick: function(ctx, textLen, lineNum, cw, ch) {
  2.     var _ = this;
  3.     this.el.addEventListener('click', function(){
  4.         text = _.randomText(textLen);
  5.         _.drawLine(ctx, lineNum, cw, ch);
  6.         _.drawText(ctx, text, ch);
  7.     }, false)
  8. }

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

 
 
 
 
  1. new Gcode('#canvas_code', {
  2.         lineNum: 6,  // 可选
  3.         textLen: 4,  // 可选
  4.         width: 200,  // 可选
  5.         height: 50   // 可选
  6.     })

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

 
 
 
 
  1. // canvas绘制图形验证码
  2.     (function(){
  3.         function Gcode(el, option) {
  4.             this.el = typeof el === 'string' ? document.querySelector(el) : el;
  5.             this.option = option;
  6.             this.init();
  7.         }
  8.         Gcode.prototype = {
  9.             constructor: Gcode,
  10.             init: function() {
  11.                 if(this.el.getContext) {
  12.                     isSupportCanvas = true;
  13.                     var ctx = this.el.getContext('2d'),
  14.                     // 设置画布宽高
  15.                     cw = this.el.width = this.option.width || 200,
  16.                     ch = this.el.height = this.option.height || 40,
  17.                     textLen = this.option.textLen || 4,
  18.                     lineNum = this.option.lineNum || 4;
  19.                     var text = this.randomText(textLen);
  20.         
  21.                     this.onClick(ctx, textLen, lineNum, cw, ch);
  22.                     this.drawLine(ctx, lineNum, cw, ch);
  23.                     this.drawText(ctx, text, ch);
  24.                 }
  25.             },
  26.             onClick: function(ctx, textLen, lineNum, cw, ch) {
  27.                 var _ = this;
  28.                 this.el.addEventListener('click', function(){
  29.                     text = _.randomText(textLen);
  30.                     _.drawLine(ctx, lineNum, cw, ch);
  31.                     _.drawText(ctx, text, ch);
  32.                 }, false)
  33.             },
  34.             // 画干扰线
  35.             drawLine: function(ctx, lineNum, maxW, maxH) {
  36.                 ctx.clearRect(0, 0, maxW, maxH);
  37.                 for(var i=0; i < lineNum; i++) {
  38.                     var dx1 = Math.random()* maxW,
  39.                         dy1 = Math.random()* maxH,
  40.                         dx2 = Math.random()* maxW,
  41.                         dy2 = Math.random()* maxH;
  42.                     ctx.strokeStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';
  43.                     ctx.beginPath();
  44.                     ctx.moveTo(dx1, dy1);
  45.                     ctx.lineTo(dx2, dy2);
  46.                     ctx.stroke();
  47.                 }
  48.             },
  49.             // 画文字
  50.             drawText: function(ctx, text, maxH) {
  51.                 var len = text.length;
  52.                 for(var i=0; i < len; i++) {
  53.                     var dx = 30 * Math.random() + 30* i,
  54.                         dy = Math.random()* 5 + maxH/2;
  55.                     ctx.fillStyle = 'rgb(' + 255*Math.random() + ',' + 255*Math.random() + ',' + 255*Math.random() + ')';
  56.                     ctx.font = '30px Helvetica';
  57.                     ctx.textBaseline = 'middle';
  58.                     ctx.fillText(text[i], dx, dy);
  59.                 }
  60.             },
  61.             // 生成指定个数的随机文字
  62.             randomText: function(len) {
  63.                 var source = ['a', 'b', 'c', 'd', 'e',
  64.                 'f', 'g', 'h', 'i', 'j', 
  65.                 'k', 'l', 'm', 'o', 'p',
  66.                 'q', 'r', 's', 't', 'u',
  67.                 'v', 'w', 'x', 'y', 'z'];
  68.                 var result = [];
  69.                 var sourceLen = source.length;
  70.                 for(var i=0; i< len; i++) {
  71.                     var text = this.generateUniqueText(source, result, sourceLen);
  72.                     result.push(text)
  73.                 }
  74.                 return result.join('')
  75.             },
  76.             // 生成唯一文字
  77.             generateUniqueText: function(source, hasList, limit) {
  78.                 var text = source[Math.floor(Math.random()*limit)];
  79.                 if(hasList.indexOf(text) > -1) {
  80.                     return this.generateUniqueText(source, hasList, limit)
  81.                 }else {
  82.                     return text
  83.                 }  
  84.             }
  85.         }
  86.         new Gcode('#canvas_code', {
  87.             lineNum: 6
  88.         })
  89.     })();

网站题目:Canvas入门实战之实现一个图形验证码
URL地址:http://www.mswzjz.cn/qtweb/news34/532334.html

攀枝花网站建设、攀枝花网站运维推广公司-贝锐智能,是专注品牌与效果的网络营销公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 贝锐智能