• canvas制作表单验证码


    canvas是个非常强大的组件,网页上的验证码一般都是用服务器语言制作出来的

    canvas同样是可以实现这个功能的

    下面请观看效果图:

    步骤呢其实也很简单

    HTML部分:      

    1 <form action="" id="form" method="post" onsubmit="check()">
    2     <label for="chat">请输入验证码:</label>
    3     <input type="text" id="chat">
    4     <canvas id="myCanvas" width="120" height="40"></canvas>
    5     <button type="submit" id="btn">提交</button>
    6 </form>

    CSS部分:

     1 form{
     2     width: 400px;
     3     display: flex;
     4     align-items: center;
     5     justify-content: space-between;
     6  }
     7 #chat{
     8      width: 100px;
     9      height: 30px;
    10      outline: none;
    11      font-size: 20px;
    12 }

    简单设置好表单的样式后,开始制作canvas

    这是全部js代码

      1 <script>
      2         let c = document.getElementById('myCanvas');
      3         let ctx = c.getContext('2d');
      4         let chat = document.getElementById('chat');
      5         let form = document.getElementById('form');
      6 
      7         function fun(){
      8             let draw = {
      9                 bgColor : `rgb(${255},${255},${255})`,
     10                 dot : {
     11                     num : 20,//点的个数
     12                     radius : 1//点的半径
     13                 },
     14                 line : {
     15                     num : 10,//线的个数
     16                     width : 1 //线的宽度
     17                 },
     18                 code : {
     19                     num : 4,//字母个数
     20                     text : [],//存放字母
     21                     deg : [],//存放字母旋转角度
     22                     size : 25,//字体大小
     23                     maxWidth : 20//字体最大宽度
     24                 }
     25             };
     26 
     27             //设置画布的背景颜色
     28             ctx.fillStyle = draw.bgColor;
     29             ctx.fillRect(0, 0, c.width, c.height);
     30 
     31             let x1 = null;
     32             let y1 = null;
     33             let x2 = null;
     34             let y2 = null;
     35             let color = null;
     36             let choose = null;
     37             let code = null;
     38 
     39             //小写字母的ascii码97~122,大写65~90
     40             for( let i = 0; i < draw.code.num; i ++ ){
     41                 choose = Math.floor(Math.random() * 2);
     42                 if(choose === 0){
     43                     code = Math.floor(Math.random() * 26) + 97;
     44                 }else{
     45                     code = Math.floor(Math.random() * 26) + 65;
     46                 }
     47                 draw.code.text.push(String.fromCharCode(code));
     48                 draw.code.deg.push(Math.floor(Math.random() * 61) - 30);//倾斜角度从-30到30
     49             }
     50 
     51             for( let i = 0; i < draw.code.num; i ++ ){
     52                 x1 = 10 + i * draw.code.size;
     53                 y1 = (c.height - draw.code.size) / 2 + draw.code.size;
     54                 color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;
     55 
     56                 //绘制字母
     57                 ctx.save();
     58                 ctx.beginPath();
     59                 ctx.fillStyle = color;
     60                 ctx.font = `${draw.code.size}px Microsoft YaHei`;
     61                 ctx.translate(x1 + draw.code.maxWidth / 2,y1 - draw.code.size / 2);
     62                 ctx.rotate(draw.code.deg[i] * Math.PI/180);
     63                 ctx.fillText(draw.code.text[i], - draw.code.maxWidth / 2, + draw.code.size / 2, draw.code.maxWidth);
     64                 ctx.restore();
     65             }
     66 
     67             for( let i = 0; i < draw.dot.num; i ++ ){
     68                 x1 = Math.random() * (c.width - draw.dot.radius) + draw.dot.radius;//随机点的初始横坐标
     69                 y1 = Math.random() * (c.height - draw.dot.radius) + draw.dot.radius;//随机点的初始纵坐标
     70                 color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;//随机点的颜色
     71 
     72                 //绘制点
     73                 ctx.beginPath();
     74                 ctx.fillStyle = color;
     75                 ctx.arc( x1, y1, draw.dot.radius, 0, Math.PI * 2 );
     76                 ctx.fill();
     77             }
     78 
     79             for( let i = 0; i < draw.line.num; i ++ ){
     80                 x1 = Math.random() * c.width;//线的开始横坐标
     81                 y1 = Math.random() * c.height;//线的开始纵坐标
     82                 x2 = Math.random() * c.width;//线的结束横坐标
     83                 y2 = Math.random() * c.height;//线的结束纵坐标
     84                 90                 color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;
     91 
     92                 //绘制线
     93                 ctx.beginPath();
     94                 ctx.lineWidth = draw.line.width;
     95                 ctx.strokeStyle = color;
     96                 ctx.moveTo(x1, y1);
     97                 ctx.lineTo(x2, y2);
     98                 ctx.stroke();
     99             }
    100            return(draw.code.text);//返回数组用于验证
    101         }
    102 
    103         fun();
    104 
    105         let text = fun();
    106 
    107         function check(){
    108             form.action = chat.value === text.join('') ? 'https://www.baidu.com/' : '#';
    109         }
    110     </script>

    下面我一点点说:

     1 let draw = {
     2                 bgColor : `rgb(${255},${255},${255})`,
     3                 dot : {
     4                     num : 20,//点的个数
     5                     radius : 1//点的半径
     6                 },
     7                 line : {
     8                     num : 10,//线的个数
     9                     width : 1 //线的宽度
    10                 },
    11                 code : {
    12                     num : 4,//字母个数
    13                     text : [],//存放字母
    14                     deg : [],//存放字母旋转角度
    15                     size : 25,//字体大小
    16                     maxWidth : 20//字体最大宽度
    17                 }
    18             };

    定义一个JSON数组来存放绘图所需的变量

    1 ctx.fillStyle = draw.bgColor;
    2 ctx.fillRect(0, 0, c.width, c.height);

    设置画布背景颜色

    1 let x1 = null;
    2 let y1 = null;
    3 let x2 = null;
    4 let y2 = null;
    5 let color = null;
    6 let choose = null;
    7 let code = null;

    一些绘图所需的临时变量

    我个人比较倾向于先绘制字母,再绘制点和线,这样干扰性更强

     1 for( let i = 0; i < draw.code.num; i ++ ){
     2     choose = Math.floor(Math.random() * 2);
     3     if(choose === 0){
     4         code = Math.floor(Math.random() * 26) + 97;
     5     }else{
     6         code = Math.floor(Math.random() * 26) + 65;
     7     }
     8     draw.code.text.push(String.fromCharCode(code));
     9     draw.code.deg.push(Math.floor(Math.random() * 61) - 30);//倾斜角度从-30到30
    10 }

    首先绘制字母,字母有分大写和小写,这里我就用随机数来决定大写和小

    小写字母的ascii码值97~122,大写65~90

    将随机出的字母和随机出的(字母旋转角度)推入数组

     1 for( let i = 0; i < draw.code.num; i ++ ){
     2     x1 = 10 + i * draw.code.size;
     3     y1 = (c.height - draw.code.size) / 2 + draw.code.size;
     4     color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;
     5 
     6     //绘制字母
     7     ctx.save();
     8     ctx.beginPath();
     9     ctx.fillStyle = color;
    10     ctx.font = `${draw.code.size}px Microsoft YaHei`;
    11     ctx.translate(x1 + draw.code.maxWidth / 2,y1 - draw.code.size / 2);
    12     ctx.rotate(draw.code.deg[i] * Math.PI/180);
    13     ctx.fillText(draw.code.text[i], - draw.code.maxWidth / 2, + draw.code.size / 2, draw.code.maxWidth);
    14     ctx.restore();
    15 }

    x1是字母绘制的起始横坐标,y1是起始纵坐标

    注意:绘制字符和绘制图形是不一样的

    字符的起始点位于字符的左下角,而图形的起始点位于图形的左上角

    计算出起始坐标后,随机出字母的填充颜色

    ctx.save();储存当前画笔信息,此时画笔的translate值为0,0,rotate值为0

    字符的起始点是位于左下角的,而我们想要的旋转效果是绕着字符中心旋转,起始点就应该设置在字符中心

    那么横坐标需要加上字母的1/2宽度,而纵坐标需要减去字母的高度(也就是字母的字体大小)

    ctx.translate(x1 + draw.code.maxWidth / 2,y1 - draw.code.size / 2);

    旋转字体,常规操作

    ctx.rotate(draw.code.deg[i] * Math.PI/180);

    这时候再减去刚刚变化的坐标值,回到原来的起始点

    ctx.fillText(draw.code.text[i], - draw.code.maxWidth / 2, + draw.code.size / 2, draw.code.maxWidth);

    ctx.restore();将画笔的信息重置回储存时的,也就是translate(0,0)、rotate(0),便于绘制下一个字母

     1 for( let i = 0; i < draw.dot.num; i ++ ){
     2     x1 = Math.random() * (c.width - draw.dot.radius) + draw.dot.radius;//随机点的初始横坐标
     3     y1 = Math.random() * (c.height - draw.dot.radius) + draw.dot.radius;//随机点的初始纵坐标
     4     color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;//随机点的颜色
     5 
     6     //绘制点
     7     ctx.beginPath();
     8     ctx.fillStyle = color;
     9     ctx.arc( x1, y1, draw.dot.radius, 0, Math.PI * 2 );
    10     ctx.fill();
    11 }

    绘制点,随机出点的初始横坐标和纵坐标,仍然用x1,y1,因为字母绘制完已经不需要x1,y1了,无需再定义新的变量

     1 for( let i = 0; i < draw.line.num; i ++ ){
     2     x1 = Math.random() * c.width;//线的开始横坐标
     3     y1 = Math.random() * c.height;//线的开始纵坐标
     4     x2 = Math.random() * c.width;//线的结束横坐标
     5     y2 = Math.random() * c.height;//线的结束纵坐标12     color = `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)})`;
    13 
    14     //绘制线
    15     ctx.beginPath();
    16     ctx.lineWidth = draw.line.width;
    17     ctx.strokeStyle = color;
    18     ctx.moveTo(x1, y1);
    19     ctx.lineTo(x2, y2);
    20     ctx.stroke();
    21 }

    最后绘制直线,仍然使用x1,y1做初始坐标,添加x2,y2做结束坐标

    然后我们需要验证我们在输入框中输入的验证码是否正确

    1 return(draw.code.text);

    返回储存在数组中的字母

    1 fun();
    2 let text = fun();

    运行fun()函数,再令text = fun();

    两个操作不能调换顺序,因为每次运行fun()得到的结果都是不一样的

    1 function check(){
    2     form.action = chat.value === text.join('') ? 'https://www.baidu.com/' : '#';
    3 }

    定义一个check函数来验证我们在输入框中输入的验证码是否正确

    如果正确就跳到百度,不正确就刷新页面

    但要注意的是前面html中的form标签要设置一个属性onsubmit="check()"

    这样点击提交按钮的时候就会无视其他form设置的属性,先执行check函数,验证是否正确。

    如果不设置onsubmit="check()",那么按照优先级顺序,会先执行form的action属性,会刷新页面,此时又会运行一次fun(),验证码就对不上了

    这里只是做一个简单的验证码,包括字母 + 数字,字符变形,大小写均可这些效果我就不做了。

  • 相关阅读:
    在Kubernetes集群里安装微服务DevOps平台fabric8
    Kubernetes PV/PVC使用实践
    Kubernetes集群中Service的滚动更新
    jenkins权限管理,不同用户显示不同项目
    SSH连接与自动化部署工具paramiko与Fabric
    kubernetes 之ingress
    理解Docker(8):Docker 存储之卷(Volume)
    Rancher Server HA的高可用部署实验-学习笔记
    2015 年总结
    2015 年总结
  • 原文地址:https://www.cnblogs.com/FrankLongger/p/9621912.html
Copyright © 2020-2023  润新知