在React中随机生成图形验证码

各个方法

在输入框中定义一个位置存放图形

完整代码 方便复制粘贴

import React, { Component } from 'react';
import styles from './leftLogin.scss';
import { withRouter } from 'dva/router';
import { connect } from 'dva';
import { Form, Icon, Input, Button, Checkbox } from 'antd';

@connect(({ login }) => ({
login,
}))

class leftLogin extends Component {
constructor(props) {
super(props);
this.state = {
code: '',
codeLength: 4,
fontSizeMin: 20,
fontSizeMax: 22,
backgroundColorMin: 240,
backgroundColorMax: 250,
colorMin: 10,
colorMax: 20,
lineColorMin: 40,
lineColorMax: 180,
contentWidth: 96,
contentHeight: 38,
showError: false, // 默认不显示验证码的错误信息
};
}

UNSAFE_componentWillMount() {
this.canvas = React.createRef();
}

componentDidMount() {
this.drawPic();
}

// 点击登录按钮
handleSubmit = e => {
e.preventDefault();
this.drawPic();
this.props.form.validateFields((err, values) => {
if (!err && this.state.showError !== true) {
// 调登录接口
const { dispatch } = this.props;
dispatch({
type: 'login/login',
payload: {
account: values.username,
pwd: values.password
}
})
this.props.form.setFieldsValue({
sendcode: '',
});
this.setState({
showError: false
})
}
});
}

// 跳转到忘记密码页
forget = () => {
this.props.history.push('/forget')
}

// 跳转到注册页
regist = () => {
this.props.history.push('/regist')
}

// 生成一个随机数
randomNum = (min, max) => {
return Math.floor(Math.random() * (max - min) + min)
}

drawPic = () => {
this.randomCode()
}

// 生成一个随机的颜色
randomColor(min, max) {
const r = this.randomNum(min, max)
const g = this.randomNum(min, max)
const b = this.randomNum(min, max)
return rgb(${r}, ${g}, ${b})
}

drawText(ctx, txt, i) {
ctx.fillStyle = this.randomColor(this.state.colorMin, this.state.colorMax)
let fontSize = this.randomNum(this.state.fontSizeMin, this.state.fontSizeMax)
ctx.font = fontSize + 'px SimHei'
let padding = 10;
let offset = (this.state.contentWidth - 40) / (this.state.code.length - 1)
let x = padding;
if (i > 0) {
x = padding + (i * offset)
}
let y = this.randomNum(this.state.fontSizeMax, this.state.contentHeight - 5)
if (fontSize > 40) {
y = 40
}
let deg = this.randomNum(-10, 10)
// 修改坐标原点和旋转角度
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 < 1; i++) {
ctx.strokeStyle = this.randomColor(this.state.lineColorMin, this.state.lineColorMax)
ctx.beginPath()
ctx.moveTo(this.randomNum(0, this.state.contentWidth), this.randomNum(0, this.state.contentHeight))
ctx.lineTo(this.randomNum(0, this.state.contentWidth), this.randomNum(0, this.state.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.state.contentWidth), this.randomNum(0, this.state.contentHeight), 1, 0, 2 * Math.PI)
ctx.fill()
}
}

reloadPic = () => {
this.drawPic()
this.props.form.setFieldsValue({
sendcode: '',
});
}

// 输入验证码
changeCode = e => {

if (e.target.value.toLowerCase() !== '' && e.target.value.toLowerCase() !== this.state.code.toLowerCase()) {
  this.setState({
    showError: true
  })
} else if (e.target.value.toLowerCase() === '') {
  this.setState({
    showError: false
  })
} else if (e.target.value.toLowerCase() === this.state.code.toLowerCase()) {
  this.setState({
    showError: false
  })
}

}

// 随机生成验证码
randomCode() {
let random = ''
// 去掉了I l i o O
const str = 'QWERTYUPLKJHGFDSAZXCVBNMqwertyupkjhgfdsazxcvbnm1234567890'
for (let i = 0; i < this.state.codeLength; i++) {
let index = Math.floor(Math.random() * 57);
random += str[index];
}
this.setState({
code: random
},()=>{
let canvas = this.canvas.current;
let ctx = canvas.getContext('2d')
ctx.textBaseline = 'bottom'
// 绘制背景
ctx.fillStyle = this.randomColor(this.state.backgroundColorMin, this.state.backgroundColorMax)
ctx.fillRect(0, 0, this.state.contentWidth, this.state.contentHeight)
// 绘制文字
for (let i = 0; i < this.state.code.length; i++) {
this.drawText(ctx, this.state.code[i], i)
}
this.drawLine(ctx)
this.drawDot(ctx)
})
}

render() {
const { getFieldDecorator } = this.props.form;
const suffix =





return (

<Form onSubmit={this.handleSubmit} style={{ width: '398px', margin: '0 auto', fontSize: '12px' }}>
<Form.Item>
{getFieldDecorator('username', {
rules: [{ required: true, message: '请输入用户名!' }, {
pattern: /^1[3456789]\d{9}$/,
message: '手机号格式不正确'
}],
})(
<Input
size="large"
prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />}
placeholder="请输入手机号"
/>,
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('password', {
rules: [{ required: true, message: '请输入密码!' }, {
pattern: /^.{6,}$/,
message: '密码格式不正确(不得低于6位)'
}],
})(
<Input
size="large"
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
type="password"
placeholder="请输入密码"
/>,
)}
</Form.Item>
<Form.Item>
{getFieldDecorator('sendcode', {
rules: [{ required: true, message: '请输入校验码!' },],
})(
<Input
size="large"
prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />}
suffix={suffix}
onChange={this.changeCode}
placeholder="请输入校验码"
/>,
)}
{
this.state.showError ?

请输入正确的验证码

: null
}
</Form.Item>

          <Form.Item className={this.state.showError ? styles.inputBottom : ''}>
            {getFieldDecorator('remember', {
              valuePropName: 'checked',
              initialValue: true,
            })(<Checkbox>7天内免登录</Checkbox>)}
            <a className={styles.forget} onClick={this.forget}>
              忘记密码
            </a>
            <Button
              size="large"
              type="primary"
              htmlType="submit"
              className={styles.button}
            >
              登录
            </Button>
            <a onClick={this.regist}>新用户注册</a>
          </Form.Item>
        </Form>
  </div>
);

}
}

const WrappedNormalLoginForm = Form.create({ name: 'normal_login' })(leftLogin);

export default withRouter(WrappedNormalLoginForm);

posted @ 2019-08-19 10:58  小蜗蜗蜗牛^o^  阅读(3717)  评论(2编辑  收藏  举报