图形验证码组件(ts版)
image.png代码如下:
<script lang="ts">
// 组件文件名 /src/components/c-identify.vue
import Vue, { VueConstructor } from "vue";
/**
* 组件-验证码
* @author [xingsk]
* @interface CIdentify
* @method changeCode() 修改验证码
* @split ---------------------------------------
*/
export interface CIdentify extends VueConstructor {
/**
* 修改验证码
*/
changeCode(): void;
}
/**
* 组件-验证码
* @component CIdentify
* @extends Vue
* @property { string } identifyCodes 验证码从该字段中抽取生成(ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678)
* @property { number } fontSizeMin 字体最小值(25)
* @property { number } fontSizeMax 字体最大值(35)
* @property { number } backgroundColorMin 验证码图片背景色最小值(200)
* @property { number } backgroundColorMax 验证码图片背景色最大值(220)
* @property { number } dotColorMin 背景干扰点最小值(60)
* @property { number } dotColorMax 背景干扰点最大值(120)
* @property { number } contentWidth 容器宽度(100)
* @property { number } contentHeight 容器宽度(30)
*
* @event change 修改后的验证码
*/
export const CIdentify = Vue.extend<
{
/**
* 验证码
*/
identifyCode: string;
/**
* 验证码长度
*/
codeLength: number;
},
{
/**
* 生成一个随机数
* @param min 最小值
* @param max 最大值
* @returns
*/
randomNum(min: number, max: number): number;
/**
* 生成一个随机的颜色
* @param min 最小值
* @param max 最大值
* @returns
*/
randomColor(min: number, max: number): string;
/**
* 生成验证码
*/
drawPic(): void;
/**
* 绘制文字
* @param ctx 画布
* @param txt 文字
* @param i 索引
*/
drawText(ctx: CanvasRenderingContext2D, txt: string, i: number): void;
/**
* 绘制干扰线
* @param ctx 画布
*/
drawLine(ctx: CanvasRenderingContext2D): void;
/**
* 绘制干扰点
* @param ctx 画布
*/
drawDot(ctx: CanvasRenderingContext2D): void;
/**
* 切换验证码
*/
changeCode(): void;
/**
* 生成验证码
* @param e 验证码
* @param n 验证码长度
*/
makeCode(e: string, n: number): void;
},
{},
{
/**
* 验证码从该字段中抽取生成
* @default 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
*/
identifyCodes: string;
/**
* 字体最小值
* @default 25
*/
fontSizeMin: number;
/**
* 字体最大值
* @default 35
*/
fontSizeMax: number;
/**
* 验证码图片背景色最小值
* @default 200
*/
backgroundColorMin: number;
/**
* 验证码图片背景色最大值
* @default 220
*/
backgroundColorMax: number;
/**
* 背景干扰点最小值
* @default 60
*/
dotColorMin: number;
/**
* 背景干扰点最大值
* @default 120
*/
dotColorMax: number;
/**
* 容器宽度
* @default 100
*/
contentWidth: number;
/**
* 容器高度
* @default 30
*/
contentHeight: number;
}
>({
name: "c-identify",
props: {
identifyCodes: {
type: String,
default: "ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678",
},
fontSizeMin: {
type: Number,
default: 25,
},
fontSizeMax: {
type: Number,
default: 35,
},
backgroundColorMin: {
type: Number,
default: 200,
},
backgroundColorMax: {
type: Number,
default: 220,
},
dotColorMin: {
type: Number,
default: 60,
},
dotColorMax: {
type: Number,
default: 120,
},
contentWidth: {
type: Number,
default: 100,
},
contentHeight: {
type: Number,
default: 30,
},
},
data() {
return {
identifyCode: "", // 验证码
codeLength: 4, // 验证码长度
};
},
watch: {
/**
* 监听验证码被改变后需要重新绘制图像
*/
identifyCode() {
this.drawPic();
},
},
mounted() {
this.drawPic();
this.makeCode(this.identifyCodes, 4);
},
methods: {
randomNum(min: number, max: number) {
return Math.floor(Math.random() * (max - min) + min);
},
randomColor(min: number, max: number) {
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(
"cont-canvas"
) as HTMLCanvasElement;
let ctx = canvas.getContext("2d") as CanvasRenderingContext2D;
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: CanvasRenderingContext2D, txt: string, i: number) {
ctx.fillStyle = this.randomColor(50, 160); //随机生成字体颜色
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(-30, 30);
// 修改坐标原点和旋转角度
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: CanvasRenderingContext2D) {
// 绘制干扰线
for (let i = 0; i < 4; i++) {
ctx.strokeStyle = this.randomColor(100, 200);
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: CanvasRenderingContext2D) {
// 绘制干扰点
for (let i = 0; i < 30; 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.identifyCode = "";
this.makeCode(this.identifyCodes, 4);
},
makeCode(e: string, n: number) {
for (let i = 0; i < n; i++) {
this.identifyCode += e[this.randomNum(0, e.length)];
}
this.$emit("change", this.identifyCode);
},
},
render(h) {
return h(
"div",
{
staticClass: "x-canvas-box",
staticStyle: {
overflow: "hidden",
},
style: {
width: this.contentWidth + "px",
height: this.contentHeight + "px",
},
on: {
click: () => this.changeCode(),
},
},
[
h("canvas", {
attrs: {
id: "cont-canvas",
width: this.contentWidth,
height: this.contentHeight,
},
}),
]
);
},
});
export default CIdentify;
</script>
引用组件:
1, image.png2, image.png
3, image.png
网友评论