【React】生成随机验证码

最近开发 React 中,没有找到什么好的随机生成验证码的插件,手动实现图形验证码!

PicAuthCode.jsx

import { useState, useEffect, useRef } from 'react'

export default function PicAuthCode(props) {
    PicAuthCode.defaultProps = {
        setCode: () => ""    // 更新验证码的方法,返回验证码即可
    }

    const [config] = useState({
        contentWidth: 100,
        contentHeight: 35,
        backgroundColorMin: 180,
        backgroundColorMax: 240,
        fontSizeMin: 25,
        fontSizeMax: 30,
        colorMin: 50,
        colorMax: 160,
        lineColorMin: 40,
        lineColorMax: 180,
        dotColorMin: 0,
        dotColorMax: 255,
        textStyle: { fontSize: '12px', color: 'gray', marginLeft: '6px', cursor: 'pointer', padding: '5px', userSelect: "none" }
    })
    const [identifyCode, setIdentifyCode] = useState('')

    const canvasRef = useRef()

    useEffect(() => {
        refresh()
    }, [])

    useEffect(() => {
        identifyCode && drawPic()
    })

    PicAuthCode.defaultProps = {
        setCode: () => ""      // 更新验证码的函数
    }

    const drawPic = () => {
        let canvas = canvasRef.current
        let ctx = canvas.getContext('2d')
        ctx.fillStyle = randomColor(config.backgroundColorMin, config.backgroundColorMax)
        ctx.strokeStyle = randomColor(config.backgroundColorMin, config.backgroundColorMax)
        ctx.fillRect(0, 0, config.contentWidth, config.contentHeight)
        ctx.strokeRect(0, 0, config.contentWidth, config.contentHeight)
        for (let i = 0; i < identifyCode.length; i++) {
            drawText(ctx, identifyCode[i], i)
        }
        drawLine(ctx)
        drawDot(ctx)
    }
    const randomNum = (min, max) => {
        return Math.floor(Math.random() * (max - min) + min)
    }
    const randomColor = (min, max) => {
        let r = randomNum(min, max)
        let g = randomNum(min, max)
        let b = randomNum(min, max)
        return 'rgb(' + r + ',' + g + ',' + b + ')'
    }
    const drawText = (ctx, txt, i) => {
        ctx.fillStyle = randomColor(config.colorMin, config.colorMax)
        ctx.font = randomNum(config.fontSizeMin, config.fontSizeMax) + 'px SimHei'
        ctx.textBaseline = 'alphabetic'
        let x = (i + 1) * (config.contentWidth / (identifyCode.length + 1))
        let y = randomNum(config.fontSizeMax, config.contentHeight - 12)
        let deg = 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)
    }
    const drawLine = (ctx) => {
        for (let i = 0; i < 8; i++) {
            ctx.strokeStyle = randomColor(config.lineColorMin, config.lineColorMax)
            ctx.beginPath()
            ctx.moveTo(randomNum(0, config.contentWidth), randomNum(0, config.contentHeight)) //设置起点x,y
            ctx.lineTo(randomNum(0, config.contentWidth), randomNum(0, config.contentHeight)) //绘制直线 x,y 一条当前位置到x,y点的直线
            ctx.stroke()
        }
    }
    const drawDot = (ctx) => {
        for (let i = 0; i < 100; i++) {
            ctx.fillStyle = randomColor(0, 255)
            ctx.beginPath()
            ctx.arc(randomNum(0, config.contentWidth), randomNum(0, config.contentHeight), 1, 0, 2 * Math.PI)
            ctx.fill()
        }
    }

    const refresh = () => {
        const words = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
        let code = ''
        for (let i = 0; i < 4; i++) {
            code += words[Math.floor(Math.random() * 52)]
        }
        props.setCode ? setIdentifyCode(props.setCode()) : setIdentifyCode(code)
    }

    return (
        <div style={{ margin: '3px 0px 12px 4px' }}>
            <canvas
                ref={canvasRef}
                width={config.contentWidth}
                height={config.contentHeight}
                onClick={refresh}
            />
        </div>
    )
}

Login.tsx

import PicAuthCode from './PicAuthCode';
import React, { useState } from 'react';

const Login: React.FC = () => {

  // 生成验证码 
  const setCode = () => {
     const words = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz'
     let code = ''
     for (let i = 0; i < 4; i++) {
       code += words[Math.floor(Math.random() * 52)]
     }
     setVerificationCode(code)
     return code
  }

   return (

        <div>
            <PicAuthCode setCode={setCode} />
        </div>
    )


}

实现效果

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的React验证码组件: ``` import React, { useState } from 'react'; import './验证码.css'; const 验证码 = () => { const [code, setCode] = useState(''); const [generatedCode, setGeneratedCode] = useState(''); const generateCode = () => { const code = Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000; setGeneratedCode(code.toString()); }; const handleSubmit = e => { e.preventDefault(); if (code === generatedCode) { alert('验证成功'); } else { alert('验证失败,请重新输入'); generateCode(); setCode(''); } }; return ( <div className="验证码"> <div className="code">{generatedCode}</div> <button className="generate" onClick={generateCode}> 生成验证码 </button> <form onSubmit={handleSubmit}> <input type="text" value={code} onChange={e => setCode(e.target.value)} placeholder="请输入验证码" required /> <button className="submit" type="submit"> 提交 </button> </form> </div> ); }; export default 验证码; ``` 相关CSS: ``` .验证码 { display: flex; flex-direction: column; align-items: center; font-size: 1.2rem; margin-top: 20px; } .code { font-weight: bold; margin-bottom: 10px; } .generate { background-color: #007bff; border: none; color: white; padding: 10px 20px; margin-bottom: 10px; cursor: pointer; } input[type='text'] { padding: 10px; margin-right: 10px; font-size: 1.2rem; border: none; border-bottom: 1px solid black; } .submit { background-color: #007bff; border: none; color: white; padding: 10px 20px; cursor: pointer; margin-top: 10px; } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值