Skip to content

Instantly share code, notes, and snippets.

@mcattx
Created April 1, 2019 09:48
Show Gist options
  • Save mcattx/2e1c0794855e2787d16e30e11b04bbab to your computer and use it in GitHub Desktop.
Save mcattx/2e1c0794855e2787d16e30e11b04bbab to your computer and use it in GitHub Desktop.
纯前端图形验证码
class Verify {
constructor(options = {}) {
this.defaultConfig = {
id: '',
canvasId: 'verifyCanvas',
width: '100',
height: '30',
// 默认 blend - 数字字母混合类型, number - 纯数字, letter 纯字母
type: 'blend',
code: ''
}
this.config = Object.assign({}, this.defaultConfig, options)
this.config.version = '0.1.0'
this.config.numberRange = '0,1,2,3,4,5,6,7,8,9'.split(',')
this.config.letterRange = this._getAllLetter()
this.init()
this.refresh()
}
getVersion() {
return this.config.version
}
init() {
const dom = document.getElementById(this.config.id)
const canvas = document.createElement('canvas')
canvas.id = this.config.canvasId
canvas.width = this.config.width
canvas.height = this.config.height
canvas.style.cursor = 'pointer'
canvas.innerHTML = '您的浏览器版本不支持 canvas'
dom.appendChild(canvas)
canvas.onclick = () => {
this.refresh()
}
}
refresh() {
this.config.code = ''
const canvas = document.getElementById(this.config.canvasId)
const ctx = canvas.getContext('2d')
ctx.textBaseline = 'middle'
ctx.fillStyle = this._randomColor(180, 240)
ctx.fillRect(0, 0, this.config.width, this.config.height)
var textRange = ''
if (this.config.type === 'blend') {
textRange = this.config.numberRange.concat(this.config.letterRange)
} else if (this.config.type === 'number') {
textRange = this.config.numberRange
} else {
textRange = this.config.letterRange
}
for (let i = 0; i < 4; i++) {
const text = textRange[this._randomNumber(0, textRange.length)]
this.config.code += text
ctx.font = '24px SimHei'
ctx.fillStyle = this._randomColor(50, 160)
ctx.shadowOffsetX = this._randomNumber(-3, 3)
ctx.shadowOffsetY = this._randomNumber(-3, 3)
ctx.shadowBlur = this._randomNumber(-3, 3)
ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'
const x = this.config.width / 5 * i
const y = this.config.height / 2
const deg = this._randomNumber(-30, 30)
// 设置旋转角度和坐标原点
ctx.translate(x, y)
ctx.rotate(deg * Math.PI / 180)
ctx.fillText(text, 0, 0)
// 恢复旋转角度和坐标原点
ctx.rotate(-deg * Math.PI / 180)
ctx.translate(-x, -y)
}
// 绘制干扰线
for (let i = 0; i < 4; i++) {
ctx.strokeStyle = this._randomColor(40, 180)
ctx.beginPath()
ctx.moveTo(this._randomNumber(0, this.config.width / 2), this._randomNumber(0, this.config.height / 2))
ctx.lineTo(this._randomNumber(0, this.config.width / 2), this._randomNumber(0, this.config.height))
ctx.stroke()
}
// 绘制干扰点
for (let i = 0; i < this.config.width / 4; i++) {
ctx.fillStyle = this._randomColor(0, 255)
ctx.beginPath()
ctx.arc(this._randomNumber(0, this.config.width), this._randomNumber(0, this.config.height), 1, 0, 2 * Math.PI)
ctx.fill()
}
}
validate(code) {
const verifyCode = code.toLowerCase()
const codeStr = this.config.code.toLowerCase()
if (verifyCode === codeStr) {
return true
} else {
return false
}
}
// 辅助方法
_getAllLetter() {
const result = 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z'
return result.split(',')
}
_randomNumber(min, max) {
return Math.floor(Math.random() * (max - min) + min)
}
_randomColor(min, max) {
const r = this._randomNumber(min, max)
const g = this._randomNumber(min, max)
const b = this._randomNumber(min, max)
return `rgb(${r}, ${g}, ${b})`
}
}
export default Verify
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment