自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Canvas入門實(shí)戰(zhàn)之實(shí)現(xiàn)一個(gè)圖形驗(yàn)證碼

開(kāi)發(fā) 前端
本文主要介紹用canvas實(shí)現(xiàn)圖形驗(yàn)證碼的一些思路以及如何用javascript面向?qū)ο蟮姆绞礁押玫膶?shí)現(xiàn)canvas的功能,關(guān)于canvas的一些基本使用方法和API我整理了一個(gè)思維導(dǎo)圖,大家感興趣的可以參考學(xué)習(xí)。

[[358782]]

 本文主要介紹用canvas實(shí)現(xiàn)圖形驗(yàn)證碼的一些思路以及如何用javascript面向?qū)ο蟮姆绞礁押玫膶?shí)現(xiàn)canvas的功能,關(guān)于canvas的一些基本使用方法和API我整理了一個(gè)思維導(dǎo)圖,大家感興趣的可以參考學(xué)習(xí)。 

 

你將收獲

  • 閉包的使用
  • canvas常用api的使用
  • javascript面向?qū)ο蟮膶?shí)現(xiàn)方式
  • 實(shí)現(xiàn)一個(gè)canvas的圖形驗(yàn)證碼的一般思路和常用算法

設(shè)計(jì)思路

  1. 用canvas生成畫(huà)布
  2. 用canvas畫(huà)干擾線或躁點(diǎn)
  3. 生成隨機(jī)不重復(fù)的n的字母
  4. 用canvas繪制文字
  5. 初始化和canvas點(diǎn)擊事件
  6. 組件化封裝

文末將附上組件封裝的源碼,歡迎大家隨時(shí)溝通交流。關(guān)于項(xiàng)目的打包,我將使用自己基于gulp4搭建的9012教你如何使用gulp4開(kāi)發(fā)項(xiàng)目腳手架。

效果預(yù)覽

圖片

實(shí)現(xiàn)思路

我將按照上文中的設(shè)計(jì)思路的步驟一步步實(shí)現(xiàn),首先我們先定義一個(gè)es5類:

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

其中init是用來(lái)初始化用的,參數(shù)el代表需要掛載的元素或元素id,option為傳入的可選項(xiàng),稍后會(huì)在代碼中體現(xiàn),通常這也是面向?qū)ο蟮某S锰茁贰?/p>

1.繪制畫(huà)布

  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.             // 設(shè)置畫(huà)布寬高 
  8.             cw = this.el.width = this.option.width || 200, 
  9.             ch = this.el.height = this.option.height || 40; 
  10.         } 
  11.     } 

這里我們?cè)诔跏蓟椒ㄖ邢榷x一個(gè)canvas畫(huà)布,寬高為用戶自定義的寬高,默認(rèn)為200*40。

2.繪制干擾線

  1. // 畫(huà)干擾線 
  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.     } 

這里我們對(duì)類Gcode定義原型方法drawLine,然后通過(guò)for循環(huán)繪制隨機(jī)位置的線條,為了讓canvas每次點(diǎn)擊能清空之前的干擾線,我們使用clearRect來(lái)清除畫(huà)布。

3.生成隨機(jī)不重復(fù)的n個(gè)字符

我們通過(guò)遞歸實(shí)現(xià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. // 生成指定個(gè)數(shù)的隨機(jī)文字 
  10. randomText: function(len) { 
  11.     var source = ['a''b''c''d''e'
  12.     'f''g''h''i''j',  
  13.     'k''l''m''o''p'
  14.     'q''r''s''t''u'
  15.     'v''w''x''y''z']; 
  16.     var result = []; 
  17.     var sourceLen = source.length; 
  18.     for(var i=0; i< len; i++) { 
  19.         var text = this.generateUniqueText(source, result, sourceLen); 
  20.         result.push(text) 
  21.     } 
  22.     return result.join(''

我們通過(guò)定義一個(gè)字母表,傳入生成的隨機(jī)字母的個(gè)數(shù),配合generateUniqueText來(lái)實(shí)現(xiàn)生成唯一不重復(fù)的n個(gè)隨機(jī)字符。當(dāng)然筆者認(rèn)為這個(gè)方法并不優(yōu)雅,你也可以使用uuid的方式或者更好的方式,歡迎隨時(shí)和筆者交流。

4.用canvas繪制文字

  1. // 畫(huà)文字 
  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. }, 

這里和上文畫(huà)線實(shí)現(xiàn)類似。就不做過(guò)多介紹了。

5.初始化和canvas點(diǎn)擊事件

接下來(lái)我們看看完整的初始化代碼:

  1. init: function() { 
  2.     if(this.el.getContext) { 
  3.         isSupportCanvas = true
  4.         var ctx = this.el.getContext('2d'), 
  5.         // 設(shè)置畫(huà)布寬高 
  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.  
  12.         this.onClick(ctx, textLen, lineNum, cw, ch); 
  13.         this.drawLine(ctx, lineNum, cw, ch); 
  14.         this.drawText(ctx, text, ch); 
  15.     } 

點(diǎn)擊事件主要是為了用戶點(diǎn)擊可以切換驗(yàn)證碼:

  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

到此,一個(gè)完整的驗(yàn)證碼組件實(shí)現(xiàn)完成,怎么用呢?如下:

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

完整代碼如下,歡迎學(xué)習(xí)交流:

  1. // canvas繪制圖形驗(yàn)證碼 
  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.                     // 設(shè)置畫(huà)布寬高 
  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.             // 畫(huà)干擾線 
  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.             // 畫(huà)文字 
  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.             // 生成指定個(gè)數(shù)的隨機(jī)文字 
  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.     })(); 

 

責(zé)任編輯:姜華 來(lái)源: 趣談前端
相關(guān)推薦

2009-11-23 16:59:23

PHP圖形驗(yàn)證碼

2020-01-06 13:11:30

技術(shù)工具

2021-08-11 06:57:17

驗(yàn)證碼圖片顯示

2015-09-21 15:31:05

php實(shí)現(xiàn)驗(yàn)證碼

2024-12-09 10:21:30

2023-09-22 11:51:13

PythonFlask

2015-12-11 09:54:47

2009-12-16 15:46:41

Ruby on rai

2018-09-18 10:11:21

前端vue.jsjavascript

2024-07-30 08:59:22

2013-06-19 10:19:59

2020-09-29 06:43:12

Java

2009-06-26 15:17:27

jQuery

2020-11-16 07:28:53

驗(yàn)證碼

2009-08-11 14:05:28

JSP驗(yàn)證碼

2009-02-09 14:17:36

2021-01-19 10:29:34

短信驗(yàn)證碼密碼

2017-12-21 07:38:19

2015-03-23 17:58:04

驗(yàn)證碼倒計(jì)時(shí)并行
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)