最近项目中要用到图片验证码,网上一查有很多,基本都是千篇一律的4位纯数字验证码。首先得感谢那位一代目兄台提供的模板,由于不能满足需求,所以对其进行了改造升级。

经改造的图片验证码能满足一下情形使用:①、验证码位数;②、纯数字和纯字母的验证码;③、数字和字母混合的验证码;④、字母的大小写;⑤、数字和字母(大小写)混合下各自的位数;⑥、随机生成混合情况下各自的位数;⑦、验证码随机排序。大致就这些组合吧,基本的需求都能满足,话不多说,看~

1、先把一代目兄台的canvas参数搬一下

参数 说明 类型 默认值
identifyCode 展示的图片验证码 string 1234
fontSizeMin 字体大小,最小值 number 16
fontSizeMax 字体大小,最大值 number 40
backgroundColorMin 背景颜色色值最小值,最小为 number 180
backgroundColorMax 背景颜色色值最大值,最大为255 number 240
colorMin 字体颜色色值最小值,最小为0 number 50
colorMax 字体颜色色值最大值,最大为255 number 160
lineColorMin 干扰线颜色色值最小值,最小为0 number 40
lineColorMax 干扰线颜色色值最大值,最大为255 number 180
dotColorMin 干扰点颜色色值最小值,最小为0 number 0
dotColorMax 干扰点颜色色值最大值,最大为255 number 255
contentWidth 画布宽度 number 160
contentHeight 画布高度 number 40

2、主角儿identify.vue组件登场

<template>
<canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas>
</template>
<script>
export default {
name: 'SIdentify',
props: {
// 图片验证码
identifyCode: {
type: String,
default: '1234'
},
// 字体最小值
fontSizeMin: {
type: Number,
default: 28
},
// 字体最大值
fontSizeMax: {
type: Number,
default: 34
},
// 背景颜色色值最小值,最小为0
backgroundColorMin: {
type: Number,
default: 200
},
// 背景颜色色值最大值,最大为255
backgroundColorMax: {
type: Number,
default: 240
},
// 字体颜色色值最小值,最小为0
colorMin: {
type: Number,
default: 0
},
// 字体颜色色值最大值,最大为255
colorMax: {
type: Number,
default: 180
},
// 干扰线颜色色值最小值,最小为0
lineColorMin: {
type: Number,
default: 150
},
// 干扰线颜色色值最大值,最大为255
lineColorMax: {
type: Number,
default: 200
},
// 干扰点颜色色值最小值,最小为0
dotColorMin: {
type: Number,
default: 100
},
// 干扰点颜色色值最大值,最大为255
dotColorMax: {
type: Number,
default: 250
},
// 画布宽度
contentWidth: {
type: Number,
default: 100
},
// 画布高度
contentHeight: {
type: Number,
default: 40
}
},
mounted () {
this.drawPic()
},
methods: {
/**
* 生成一个随机数
* @param {number} min 随机数最小值
* @param {number} max 随机数最大值
*/
randomNum (min, max) {
return Math.floor(Math.random() * (max - min) + min)
}, /**
* 生成一个随机的颜色
* @param {number} min 随机数最小值
* @param {number} max 随机数最大值
*/
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 + ')'
}, /**
* 绘制图片验证码
*/
drawPic () {
let canvas = document.querySelector('#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)
// 绘制干扰点
this.drawDot(ctx)
// 绘制验证码
for (let i = 0; i < this.identifyCode.length; i++) {
this.drawText(ctx, this.identifyCode[i], i)
}
// 绘制干扰线
this.drawLine(ctx)
}, /**
* 绘制文本单个验证码
* @param {object} ctx canvas上下文对象
* @param {string} txt 单个验证码
* @param {number} i 单个验证码序号
*/
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)
let 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)
}, /**
* 绘制干扰线
* @param {object} ctx canvas上下文对象
*/
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()
}
}, /**
* 绘制干扰点
* @param {object} ctx canvas上下文对象
*/
drawDot (ctx) {
for (let i = 0; i < 60; 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()
}
}
}
</script>

3、对图片验证码组件的引用

为了方便演示,直接在App.vue页面中引用

<template>
<div id="app" @click="refreshCode">
<s-identify :identifyCode="identifyCode"></s-identify>
</div>
</template> <script>
import SIdentify from './components/identify'
export default {
name: 'App',
data () {
return {
makeCode: '',
identifyCode: ''
}
},
mounted () {
this.makeIdentifyCode({ randomTypeLen: true })
},
methods: {
/**
* 随机生成一个0~9之间的数
*/
randomNum () {
return Math.floor(Math.random() * 10)
}, /**
* 随机生成一个字母
* @param {boolean} isUupper 生成大写字母
*/
randomAlphabet ({ isUupper = false } = {}) {
// a的Unicode值为97,z的Unicode值为123
const alphabet = String.fromCharCode(Math.floor(Math.random() * 25) + 97)
if (!isUupper) {
return alphabet
} else {
return alphabet.toUpperCase()
}
}, /**
* 生成图片验证码
* @param {number} length 图片验证码位数
* @param {boolean} typeMix 数字和字母混合
* @param {string} pureNumber 纯数字('number')或者字母('alphabet')
* @param {boolean} randomTypeLen 随机生成类型个数组合
* @param {boolean} capsLookMix 字母大小写混合
* @param {number} numLength 混合类型下的数字个数
* @param {number} uupperLength 大写字母的个数
*/
makeIdentifyCode ({ length = 4, typeMix = true, pureNumber = 'alphabet', randomTypeLen = false, capsLookMix = false, numLength = 2, uupperLength = 1 } = {}) {
this.makeCode = ''
// 数字和字母混合
if (typeMix) {
// 随机生成类型个数组合
if (randomTypeLen) {
// 字母大小写混合
if (capsLookMix) {
const numLength = Math.floor(Math.random() * length) + 1
const uupperLength = numLength === length ? 0 : Math.floor(Math.random() * (length - numLength)) + 1
for (let i = 0; i < numLength; i++) {
this.makeCode += this.randomNum()
}
for (let i = 0; i < uupperLength; i++) {
this.makeCode += this.randomAlphabet({ isUupper: true })
}
if (numLength + uupperLength < length) {
for (let i = 0; i < length - numLength - uupperLength; i++) {
this.makeCode += this.randomAlphabet()
}
}
} else {
const numLength = Math.floor(Math.random() * length) + 1
for (let i = 0; i < numLength; i++) {
this.makeCode += this.randomNum()
}
if (numLength < length) {
for (let i = 0; i < length - numLength; i++) {
this.makeCode += this.randomAlphabet()
}
}
}
} else {
// 字母大小写混合
if (capsLookMix) {
const tempNumLength = numLength < 0 ? 2 : numLength > length ? 2 : numLength
const tempUupperLength = uupperLength < 0 ? 1 : uupperLength > length - tempNumLength ? 1 : uupperLength
for (let i = 0; i < tempNumLength; i++) {
this.makeCode += this.randomNum()
}
for (let i = 0; i < tempUupperLength; i++) {
this.makeCode += this.randomAlphabet({ isUupper: true })
}
if (tempNumLength + tempUupperLength < length) {
for (let i = 0; i < length - tempNumLength - tempUupperLength; i++) {
this.makeCode += this.randomAlphabet()
}
}
} else {
const tempNumLength = numLength < 0 ? 2 : numLength > length ? 2 : numLength
for (let i = 0; i < tempNumLength; i++) {
this.makeCode += this.randomNum()
}
if (tempNumLength < length) {
for (let i = 0; i < length - tempNumLength; i++) {
this.makeCode += this.randomAlphabet()
}
}
}
}
} else {
// 纯数字('number')
if (pureNumber === 'number') {
for (let i = 0; i < length; i++) {
this.makeCode += this.randomNum()
}
}
// 纯字母('alphabet')
if (pureNumber === 'alphabet') {
// 字母大小写混合
if (capsLookMix) {
const tempUupperLength = uupperLength < 0 ? 1 : uupperLength > length ? 1 : uupperLength
for (let i = 0; i < tempUupperLength; i++) {
this.makeCode += this.randomAlphabet({ isUupper: true })
}
if (tempUupperLength < length) {
for (let i = 0; i < length - tempUupperLength; i++) {
this.makeCode += this.randomAlphabet()
}
}
} else {
for (let i = 0; i < length; i++) {
this.makeCode += this.randomAlphabet()
}
}
}
}
this.shuffle(this.makeCode)
}, /**
* 图片验证码随机排序
* @param {string} str 图片验证码
*/
shuffle (str) {
this.identifyCode = [...str].sort(() => Math.random() - 0.5).join('')
console.log(this.identifyCode)
}, /**
* 更换图片验证码
*/
refreshCode () {
this.makeIdentifyCode({ randomTypeLen: true })
}
},
components: {
's-identify': SIdentify
}
}
</script>

就这样吧,完事儿~

Vue图片验证码-自定义组件高级版的更多相关文章

  1. vue.js2.0 自定义组件初体验

    理解 组件(Component)是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素, Vue.js 的编译器为它添加特殊功能.在有些情况 ...

  2. vue图片上传组件

    前言:很多项目中都需要用到图片上传功能,而其多处使用的要求,为了避免重复造轮子,让我决定花费一些时间去深入了解,最终封装了一个vue的图片上传组件.现将总结再次,希望有帮助. Layout <d ...

  3. VUE 图片验证码

    1. 概述 1.1 说明 在开发过程中,有时候需要使用图片验证码进行增加安全强度,在点击图片时更新新的图片验证码,记录此功能,以便后期使用. 2. 示例 2.1 vue示例代码 <templat ...

  4. Vue.extend提供自定义组件的构造器

    Vue.extend 返回的是一个“扩展实例构造器”,也就是预设了部分选项的Vue实例构造器.经常服务于Vue.component用来生成组件,可以简单理解为当在模板中遇到该组件名称作为标签的自定义元 ...

  5. vue框架之自定义组件中使用v-model

    通常 vue在html常见表单空间支持v-model双向绑定例如 <input v-model="message" placeholder="edit me&quo ...

  6. vue怎么给自定义组件绑定原生事件

     下面主要以4个示例Demo演示(示例代码JS引用的Vue CDN),建议小伙伴直接复制示例代码运行查看, 赶时间的小伙伴可直接往下拉,看示例demo4 注:全局或局部注册的组件称为子组件,其中声明的 ...

  7. vue之全局自定义组件

    在项目开发中,往往需要使用到一些公共组件,比如,弹出消息.面包屑或者其它的组件,为了使用方便,将其以插件的形式融入到vue中,以面包屑插件为例: 1.创建公共组件MyBread.vue <tem ...

  8. Vue 获取验证码倒计时组件

    子组件 <template> <a class="getvalidate":class="{gray: (!stop)}"@click='cl ...

  9. Vue第一个自定义组件:数字输入框(number-input)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. HTTP&&Fiddler教程

    很不错的学习资料! HTTP http://www.cnblogs.com/TankXiao/category/415412.html http://www.cnblogs.com/TankXiao/ ...

  2. 网络最大流(EK)

    以前在oi中见到网络流的题都是直接跳过,由于本蒟蒻的理解能力太弱,导致网络流的学习不断推迟甚至被安排在了tarjan之后,原本计划于学习完最短路后就来学网络流的想法也随之破灭,在看完众多大佬 的博客后 ...

  3. 《Python学习手册 第五版》 -第8章 列表与字典

    前面已经讲过数值类型(第5章)和字符串类型(第7章),本章继续其他数据类型的讲解:列表和字典 本章的核心内容 1.列表 1)什么是列表 2)基本列表操作 3)列表迭代和推导 4)索引.分片和矩阵 5) ...

  4. java设计模式7——桥接模式

    java设计模式7--桥接模式 1.桥接模式介绍 桥接模式是将抽象部分与它的实现部分分离,使他们都可以独立的变化.它是一种对象结构型模式,又称为柄体模式或接口模式. 2.解决问题 2.1.将复杂的组合 ...

  5. num07---工厂方法模式

    一.简单工厂模式 [之所以叫简单,说明没有完全做到 设计模式的要求] 前言:活字印刷术,面向对象思想 复用 维护 扩展 灵活 高内聚低耦合 以 实现 一个计算器 为例: 1.创建 抽象类count, ...

  6. Elasticsearch与中文分词配置

    一. elasticsearch on windows 1.下载地址: https://www.elastic.co/cn/downloads/elasticsearch 如果浏览器下载文件慢,建议使 ...

  7. [转]java 为什么wait(),notify(),notifyAll()必须在同步方法/代码块中调用?

    在 Java中,所有对象都能够被作为"监视器monitor"——指一个拥有一个独占锁,一个入口队列和一个等待队列的实体entity. 所有对象的非同步 方法都能够在任意时刻被任意线 ...

  8. 《Head first设计模式》之命令模式

    命令模式将"请求"封装成对象,以便使用不同的请求.队列或者日志来参数化其他对象.命令模式也支持可撤销的操作. 一个家电公司想邀请你设计一个家电自动化遥控器的API.这个遥控器有7个 ...

  9. 线段树学习----C语言

    /* 线段树学习:如果一个节点为i,那么他的左孩子为2I+1,右孩子为2i+2: */ #include<stdio.h> #define min(a,b) a<b?a:b; ]; ...

  10. c语言标准I/O

    头文件 <stdio.h> 打开/关闭文件 FILE *fopen(char *filename, char *mode); 如果正常打开返回FILE指针,否则返回NULL mode常用值 ...