zoukankan      html  css  js  c++  java
  • canvas实现验证码

    在通常的登录界面我们都可以看到验证码,验证码的作用是检测是不是人在操作,防止机器等非人操作,防止数据库被轻而易举的攻破。

    验证码一般用PHP和java等后端语言编写。

    但是在前端,用canva或者SVG也可以绘制验证码。

    绘制验证码不能是简单的随机字符串,而应该在绘制界面有一些干扰项:

    如:干扰线段干扰圆点背景等等。

    这里的这个demo的canvas验证码干扰项比较简单。

    可以在图示中看到本例中的干扰项。

    canvas验证码展示效果:

    点击实现改变(重绘)验证码:

    在控制台运行函数输出返回值(验证码):

    源码

      1 <!DOCTYPE html>
      2 <html lang="en">
      3 
      4 <head>
      5     <meta charset="UTF-8">
      6     <meta name="viewport" content="width=device-width, initial-scale=1.0">
      7     <meta http-equiv="X-UA-Compatible" content="ie=edge">
      8     <title>canvas验证码</title>
      9 </head>
     10 
     11 <body>
     12     <canvas width="200" height="60" id="check" style="border:1px solid #000;">您的浏览器不支持canvas标签!</canvas>
     13     <script>
     14         var ctx = document.getElementById("check").getContext("2d");
     15         var ctxW = document.getElementById("check").clientWidth;
     16         var ctxH = document.getElementById("check").clientHeight;
     17 
     18         /**
     19          * 产生一个随机数  可设置随机数区间
     20          * @param  {[Number]} min [随机数区间下限]
     21          * @param  {[Number]} max [随机数区间上限]
     22          * @return {[Number]}     [返回一个在此区间的随机数]
     23          */
     24         function ranNum(min, max) {
     25 
     26             return Math.random() * (max - min) + min;
     27 
     28         }
     29 
     30         /**
     31          * 返回一个随机颜色 可设置颜色区间
     32          * @param  {[Number]} min [颜色下限]
     33          * @param  {[Number]} max [颜色上限]
     34          * @return {[String]}     [随机颜色]
     35          */
     36         function ranColor(min, max) {
     37 
     38             var r = ranNum(min, max);
     39 
     40             var g = ranNum(min, max);
     41 
     42             var b = ranNum(min, max);
     43 
     44             // return "rgb(" + r + "," + g + "," + b + ")";
     45             return `rgb(${r},${g},${b})`;
     46 
     47         }
     48 
     49         /**
     50          * 随机字符串数组
     51          * @return {[Array]} [随机数组]
     52          */
     53         function ranStr() {
     54 
     55             var str = "QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm0123456789";
     56 
     57             return str.split("").sort(function () {
     58                 return Math.random() - 0.5
     59             });
     60 
     61         }
     62 
     63         /**
     64          * 绘制文本字符串
     65          * @param  {[String]} canvasId [canvas的id]
     66          * @param  {[Number]} canvasW  [canvas的width]
     67          * @param  {[Number]} canvasH  [canvas的height]
     68          * @param  {[Number]} num      [绘制验证码的字数]
     69          * @param  {[Number]} fsMin    [字体大小下限]
     70          * @param  {[Number]} fsMax    [字体大小上限]
     71          * @param  {[Number]} frMin    [字体旋转偏移下限]
     72          * @param  {[Number]} frMax    [字体旋转偏移上限]
     73          * @param  {[Number]} min      [颜色下限]
     74          * @param  {[Number]} max      [颜色上限]
     75          * @return {[String]} [随机字符串]
     76          */
     77         function drawText(canvasId, canvasW, canvasH, num, fsMin, fsMax, frMin, frMax, min, max) {
     78 
     79             var str = "";
     80 
     81             for (var i = 0; i < num; i++) {
     82 
     83                 var char = ranStr()[Math.floor(0, ranStr().length)];
     84 
     85                 var fs = ranNum(fsMin, fsMax);
     86 
     87                 canvasId.font = fs + "px Verdana";
     88 
     89                 canvasId.fillStyle = ranColor(min, max);
     90 
     91                 // 保存绘制的状态
     92                 canvasId.save();
     93 
     94                 // context.translate(x,y);
     95                 // x    添加到水平坐标(x)上的值
     96                 // y    添加到垂直坐标(y)上的值
     97                 // 偏移
     98                 canvasId.translate(canvasW / num * i + canvasW / 20, 0);
     99 
    100                 // 变换角度
    101                 canvasId.rotate(ranNum(frMin, frMax) * Math.PI / 180);
    102 
    103                 // context.fillText(text,x,y,maxWidth);
    104                 // text    规定在画布上输出的文本。
    105                 // x    开始绘制文本的 x 坐标位置(相对于画布)。
    106                 // y    开始绘制文本的 y 坐标位置(相对于画布)。
    107                 // maxWidth    可选。允许的最大文本宽度,以像素计。
    108                 canvasId.fillText(char, 0, (canvasH + fs) / 2.5, canvasW / num);
    109 
    110                 // 返回之前保存过的路径状态和属性
    111                 ctx.restore();
    112 
    113                 str += char;
    114 
    115             }
    116 
    117             // console.log(str);
    118             return str;
    119 
    120         }
    121 
    122         /**
    123          * 绘制背景
    124          * @param  {[String]} canvasId [canvas的id]
    125          * @param  {[Number]} canvasW  [canvas的width]
    126          * @param  {[Number]} canvasH  [canvas的height]
    127          * @param  {[Number]} min      [下限]
    128          * @param  {[Number]} max      [上限]
    129          */
    130         function drawBg(canvasId, canvasW, canvasH, min, max) {
    131 
    132             // 绘制canvas背景
    133             canvasId.fillStyle = ranColor(min, max);
    134 
    135             // 填充颜色
    136             canvasId.fillRect(0, 0, canvasW, canvasH);
    137 
    138         }
    139 
    140         /**
    141          * 绘制干扰 圆点
    142          * @param  {[String]} canvasId [canvas的id]
    143          * @param  {[Number]} canvasW  [canvas的width]
    144          * @param  {[Number]} canvasH  [canvas的height]
    145          * @param  {[Number]} num      [绘制的数量]
    146          * @param  {[Number]} r        [圆点半径]
    147          * @param  {[Number]} min      [下限]
    148          * @param  {[Number]} max      [上线]
    149          */
    150         function drawCircle(canvasId, canvasW, canvasH, num, r, min, max) {
    151 
    152             for (var i = 0; i < num; i++) {
    153 
    154                 // 开始绘制 (拿起笔)
    155                 canvasId.beginPath();
    156 
    157                 // context.arc(x,y,r,sAngle,eAngle,counterclockwise); (绘制)
    158                 // x    圆的中心的 x 坐标。
    159                 // y    圆的中心的 y 坐标。
    160                 // r    圆的半径。
    161                 // sAngle    起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
    162                 // eAngle    结束角,以弧度计。
    163                 // counterclockwise    可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。
    164                 canvasId.arc(ranNum(0, canvasW), ranNum(0, canvasH), r, 0, 2 * Math.PI);
    165 
    166                 // 填充颜色
    167                 canvasId.fillStyle = ranColor(min, max);
    168 
    169                 // 填充
    170                 canvasId.fill();
    171 
    172                 // 闭合绘制 (放开笔)
    173                 canvasId.closePath();
    174 
    175             }
    176 
    177         }
    178 
    179         /**
    180          * 绘制干扰 线段
    181          * @param  {[String]} canvasId [canvas的id]
    182          * @param  {[Number]} canvasW  [canvas的width]
    183          * @param  {[Number]} canvasH  [canvas的height]
    184          * @param  {[Number]} num      [绘制的数量]
    185          * @param  {[Number]} min      [下限]
    186          * @param  {[Number]} max      [上线]
    187          */
    188         function drawLine(canvasId, canvasW, canvasH, num, min, max) {
    189 
    190             for (var i = 0; i < num; i++) {
    191 
    192                 // 开始绘制 (拿起笔)
    193                 canvasId.beginPath();
    194 
    195                 // 绘制开始点
    196                 canvasId.moveTo(ranNum(0, canvasW), ranNum(0, canvasH));
    197 
    198                 // 绘制结束点
    199                 canvasId.lineTo(ranNum(0, canvasW), ranNum(0, canvasH));
    200 
    201                 canvasId.strokeStyle = ranColor(min, max);
    202 
    203                 canvasId.stroke();
    204 
    205                 canvasId.closePath();
    206 
    207             }
    208 
    209         }
    210 
    211         // 绘制验证码
    212         function drawCanvas() {
    213 
    214             // 清空canvas
    215             ctx.clearRect(0, 0, 200, 60);
    216 
    217             // 绘制背景
    218             drawBg(ctx, ctxW, ctxH, 200, 255);
    219 
    220             // 绘制干扰圆点
    221             drawCircle(ctx, ctxW, ctxH, 20, 5, 200, 255);
    222 
    223             // 绘制干扰线段
    224             drawLine(ctx, ctxW, ctxH, 20, 0, 255);
    225 
    226             // 绘制验证码
    227             var str = drawText(ctx, ctxW, ctxH, 4, 10, 50, -30, 30, 0, 100);
    228 
    229             return str;
    230 
    231         }
    232 
    233         drawCanvas();
    234 
    235         document.getElementById('check').onclick = drawCanvas;
    236     </script>
    237 </body>
    238 
    239 </html>
  • 相关阅读:
    2.12 使用@DataProvider
    2.11 webdriver中使用 FileUtils ()
    Xcode8 添加PCH文件
    The app icon set "AppIcon" has an unassigned child告警
    Launch Image
    iOS App图标和启动画面尺寸
    iPhone屏幕尺寸、分辨率及适配
    Xcode下载失败 使用已购项目页面再试一次
    could not find developer disk image
    NSDate与 NSString 、long long类型的相互转化
  • 原文地址:https://www.cnblogs.com/lprosper/p/9504968.html
Copyright © 2011-2022 走看看