一个前端,爱跑步、爱吉他、爱做饭、爱生活、爱编程、爱南芳姑娘,爱我所爱。世间最温暖又无价的是阳光、空气与爱,愿它们能带你去更远的地方。

  • 文章
  • 心情
  • 照片墙
  • 工具
  • 开发技术分享

    图形验证码(react+vue)版本

    技术 276 2022-01-28 18:20

    之前vue版本的博客里面找了一款图形验证的组件,

    由于现在重新开发了react版本的博客

    图型验证码 没有找到比较好的组件,

    所以干脆看一下之前vue版本的图形验证码的源码

    直接搬过来

    先看一下效果图:

    接下来直接上代码:

    VUE版本:

    组件源码:sidentify.vue

    <template>
      <div class="s-canvas">
        <!-- 验证码组件 -->
        <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
      </div>
    </template>
    <script>
    export default {
      name: "SIdentify",
      props: {
        identifyCode: {
          type: String,
          default: "1234"
        },
        fontSizeMin: {
          type: Number,
          default: 16
        },
        fontSizeMax: {
          type: Number,
          default: 40
        },
        backgroundColorMin: {
          type: Number,
          default: 180
        },
        backgroundColorMax: {
          type: Number,
          default: 240
        },
        colorMin: {
          type: Number,
          default: 50
        },
        colorMax: {
          type: Number,
          default: 160
        },
        lineColorMin: {
          type: Number,
          default: 40
        },
        lineColorMax: {
          type: Number,
          default: 180
        },
        dotColorMin: {
          type: Number,
          default: 0
        },
        dotColorMax: {
          type: Number,
          default: 255
        },
        contentWidth: {
          type: Number,
          default: 112
        },
        contentHeight: {
          type: Number,
          default: 38
        }
      },
      methods: {
        // 生成一个随机数
        randomNum(min, max) {
          return Math.floor(Math.random() * (max - min) + min);
        },
        // 生成一个随机的颜色
        randomColor(min, max) {
          let r = this.randomNum(min, max);
          let g = this.randomNum(min, max);
          let b = this.randomNum(min, max);
          return "rgb(" + r + "," + g + "," + b + ")";
        },
        drawPic() {
          let canvas = document.getElementById("s-canvas");
          let ctx = canvas.getContext("2d");
          ctx.textBaseline = "bottom";
          // 绘制背景
          ctx.fillStyle = this.randomColor(
            this.backgroundColorMin,
            this.backgroundColorMax
          );
          ctx.fillRect(0, 0, this.contentWidth, this.contentHeight);
          // 绘制文字
          for (let i = 0; i < this.identifyCode.length; i++) {
            this.drawText(ctx, this.identifyCode[i], i);
          }
          // this.drawLine(ctx);
          // this.drawDot(ctx);
        },
        drawText(ctx, txt, i) {
          ctx.fillStyle = this.randomColor(this.colorMin, this.colorMax);
          ctx.font =
            this.randomNum(this.fontSizeMin, this.fontSizeMax) + "px SimHei";
          let x = (i + 1) * (this.contentWidth / (this.identifyCode.length + 1));
          let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5);
          var deg = this.randomNum(-45, 45);
          // 修改坐标原点和旋转角度
          ctx.translate(x, y);
          ctx.rotate((deg * Math.PI) / 180);
          ctx.fillText(txt, 0, 0);
          // 恢复坐标原点和旋转角度
          ctx.rotate((-deg * Math.PI) / 180);
          ctx.translate(-x, -y);
        }
        // drawLine(ctx) {
        //   // 绘制干扰线
        //   for (let i = 0; i < 8; i++) {
        //     ctx.strokeStyle = this.randomColor(
        //       this.lineColorMin,
        //       this.lineColorMax
        //     );
        //     ctx.beginPath();
        //     ctx.moveTo(
        //       this.randomNum(0, this.contentWidth),
        //       this.randomNum(0, this.contentHeight)
        //     );
        //     ctx.lineTo(
        //       this.randomNum(0, this.contentWidth),
        //       this.randomNum(0, this.contentHeight)
        //     );
        //     ctx.stroke();
        //   }
        // },
        // drawDot(ctx) {
        //   // 绘制干扰点
        //   for (let i = 0; i < 100; i++) {
        //     ctx.fillStyle = this.randomColor(0, 255);
        //     ctx.beginPath();
        //     ctx.arc(
        //       this.randomNum(0, this.contentWidth),
        //       this.randomNum(0, this.contentHeight),
        //       1,
        //       0,
        //       2 * Math.PI
        //     );
        //     ctx.fill();
        //   }
        // }
      },
      watch: {
        identifyCode() {
          this.drawPic();
        }
      },
      mounted() {
        this.drawPic();
      }
    };
    </script>
    <style lang="css" scoped>
    .s-canvas {
      height: 38px;
    }
    canvas {
      margin-top: 1px;
      margin-left: 8px;
    }
    </style>
    

    引用:

    import SIdentify from "./sidentify";
          <!--验证码组件-->
    // template 
    <s-identify :identifyCode="123456789"></s-identify>
    // v-data
       identifyCodes: "1234567890",
       identifyCode: "",
    // v-methods
        randomNum(min, max) {
          return Math.floor(Math.random() * (max - min) + min);
        },
        refreshCode() {
          this.identifyCode = "";
          this.makeCode(this.identifyCodes, 4);
        },
        makeCode(o, l) {
          for (let i = 0; i < l; i++) {
            this.identifyCode += this.identifyCodes[
              this.randomNum(0, this.identifyCodes.length)
            ];
          }
        },
    // v-created
      created() {
        this.refreshCode();
      },
    

    下面是react版本:

    import React, { Component } from "react";
    
    let defaultDataObj = {
      identifyCodes: {
        type: String,
        default: "1234567890",
      },
      identifyCode: {
        type: String,
        default: "1234",
      },
      fontSizeMin: {
        type: Number,
        default: 16,
      },
      fontSizeMax: {
        type: Number,
        default: 40,
      },
      backgroundColorMin: {
        type: Number,
        default: 180,
      },
      backgroundColorMax: {
        type: Number,
        default: 240,
      },
      colorMin: {
        type: Number,
        default: 50,
      },
      colorMax: {
        type: Number,
        default: 160,
      },
      lineColorMin: {
        type: Number,
        default: 40,
      },
      lineColorMax: {
        type: Number,
        default: 180,
      },
      dotColorMin: {
        type: Number,
        default: 0,
      },
      dotColorMax: {
        type: Number,
        default: 255,
      },
      contentWidth: {
        type: Number,
        default: 112,
      },
      contentHeight: {
        type: Number,
        default: 38,
      },
    };
    class SIdentify extends Component {
      constructor(props) {
        super(props);
        this.state = {};
      }
    
      // 生成一个随机数
      randomNum = (min, max) => {
        return Math.floor(Math.random() * (max - min) + min);
      };
    
      // 生成一个随机的颜色
      randomColor = (min, max) => {
        let r = this.randomNum(min, max);
        let g = this.randomNum(min, max);
        let b = this.randomNum(min, max);
        return "rgb(" + r + "," + g + "," + b + ")";
      };
    
      drawPic = () => {
        let canvas = document.getElementById("s-canvas");
        let ctx = canvas.getContext("2d");
    
        console.log(canvas);
        console.log(ctx);
        ctx.textBaseline = "bottom";
        // 绘制背景
    
        console.log(defaultDataObj.backgroundColorMin);
        ctx.fillStyle = this.randomColor(
          defaultDataObj.backgroundColorMin.default,
          defaultDataObj.backgroundColorMax.default
        );
        ctx.fillRect(
          0,
          0,
          defaultDataObj.contentWidth.default,
          defaultDataObj.contentHeight.default
        );
        // 绘制文字
        for (let i = 0; i < defaultDataObj.identifyCode.default.length; i++) {
          this.drawText(ctx, defaultDataObj.identifyCode.default[i], i);
        }
    
        this.drawLine(ctx);
        this.drawDot(ctx);
      };
    
      drawText = (ctx, txt, i) => {
        ctx.fillStyle = this.randomColor(
          defaultDataObj.colorMin.default,
          defaultDataObj.colorMax.default
        );
        ctx.font =
          this.randomNum(
            defaultDataObj.fontSizeMin.default,
            defaultDataObj.fontSizeMax.default
          ) + "px SimHei";
        let x =
          (i + 1) *
          (defaultDataObj.contentWidth.default /
            (defaultDataObj.identifyCode.default.length + 1));
        let y = this.randomNum(
          defaultDataObj.fontSizeMax.default,
          defaultDataObj.contentHeight.default - 5
        );
        var deg = this.randomNum(-45, 45);
        // 修改坐标原点和旋转角度
        ctx.translate(x, y);
        ctx.rotate((deg * Math.PI) / 180);
        ctx.fillText(txt, 0, 0);
        // 恢复坐标原点和旋转角度
        ctx.rotate((-deg * Math.PI) / 180);
        ctx.translate(-x, -y);
      };
    
      drawLine = (ctx) => {
        // 绘制干扰线
        for (let i = 0; i < 8; i++) {
          ctx.strokeStyle = this.randomColor(
            defaultDataObj.lineColorMin.default,
            defaultDataObj.lineColorMax.default
          );
          ctx.beginPath();
          ctx.moveTo(
            this.randomNum(0, defaultDataObj.contentWidth.default),
            this.randomNum(0, defaultDataObj.contentHeight.default)
          );
          ctx.lineTo(
            this.randomNum(0, defaultDataObj.contentWidth.default),
            this.randomNum(0, defaultDataObj.contentHeight.default)
          );
          ctx.stroke();
        }
      };
    
      drawDot(ctx) {
        // 绘制干扰点
        for (let i = 0; i < 100; i++) {
          ctx.fillStyle = this.randomColor(0, 255);
          ctx.beginPath();
          ctx.arc(
            this.randomNum(0, this.contentWidth),
            this.randomNum(0, this.contentHeight),
            1,
            0,
            2 * Math.PI
          );
          ctx.fill();
        }
      }
    
      changeCode = () => {
        this.refreshCode();
      };
    
      makeCode = (o, l) => {
        for (let i = 0; i < l; i++) {
          defaultDataObj.identifyCode.default +=
            defaultDataObj.identifyCodes.default[
              this.randomNum(0, defaultDataObj.identifyCodes.default.length)
            ];
        }
    
        console.log("校验", defaultDataObj.identifyCode.default);
        this.drawPic();
      };
    
      refreshCode = () => {
        defaultDataObj.identifyCode.default = "";
        this.makeCode(defaultDataObj.identifyCodes.default, 4);
      };
    
      render() {
        return (
          <div>
            验证码:
            <canvas id="s-canvas" width="112px" height="38"></canvas>
            <button onClick={this.changeCode}>切换验证码</button>
          </div>
        );
      }
    
      componentDidMount() {
        this.refreshCode();
      }
    }
    
    export default SIdentify;
    

    逻辑都一样就是写法改了一下,

    有问题可以留言