组件内容
<template>
<canvas
id="canvas"
ref="canvas"
:width="width"
:height="height"
@click="updateCanvas"
></canvas>
</template>
<script>
export default {
data() {
return {
ctx: null,
computedWidth: 0,
computedHeight: 0,
};
},
props: {
value: {
type: String,
default: "",
},
nums: {
type: Number,
default: 4,
},
width: {
type: Number,
default: 300,
},
height: {
type: Number,
default: 80,
},
color: String,
fillStyle: {
type: String,
default: "#fff",
},
randomLine: {
type: Boolean,
default: false,
},
clickUpdate: {
type: Boolean,
default: true,
},
},
mounted() {
const ramdomStr = this.getRandomStr();
this.initCanvas();
this.setCanvas(ramdomStr);
},
methods: {
initCanvas() {
const canvas = this.$refs.canvas;
const ctx = canvas.getContext("2d");
const computedStyle = getComputedStyle(canvas);
this.ctx = ctx;
this.computedWidth = parseFloat(computedStyle.width);
this.computedHeight = parseFloat(computedStyle.height);
ctx.fillStyle = this.fillStyle;
ctx.fillRect(0, 0, this.computedWidth, this.computedHeight);
this.randomLine && this.setRandomLine(ctx);
},
getRandomStr() {
const _str =
"abcdefghijkmlnopQrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let randomStr = "";
if (!this.value) {
for (var i = 0; i < this.nums; i++) {
randomStr += _str[Math.floor(Math.random() * _str.length)];
}
} else {
randomStr = this.value;
}
this.$emit("getImgCode", randomStr);
return randomStr;
},
setRandomLine(ctx) {
const computedWidth = this.computedWidth;
const computedHeight = this.computedHeight;
const nums = this.nums;
const lineNums = Math.floor(computedWidth / nums);
for (let i = 0; i < lineNums; i++) {
ctx.save();
ctx.beginPath();
ctx.strokeStyle = this.getRandomRgb();
ctx.translate(
10 + i * (computedWidth / lineNums),
Math.random() * computedHeight
);
ctx.rotate(this.getRandomDeg());
ctx.moveTo(0, 0);
ctx.lineTo(0, Math.random() * computedHeight);
ctx.stroke();
ctx.restore();
}
},
setCanvas(str) {
const len = str.length;
const ctx = this.ctx;
const fontsize = this.setFont();
const computedHeight = this.computedHeight;
const computedWidth = this.computedWidth;
ctx.font = `${fontsize}px sans-serif`;
ctx.save();
for (let i = 0; i < len; i++) {
const scaleBase = Math.random() > 0.5 ? 1.1 : 0.9;
const randomRgb = this.getRandomRgb();
ctx.fillStyle = this.color ?? randomRgb;
ctx.translate(
(computedWidth - fontsize * 4) / len + fontsize * i,
parseFloat(computedHeight) / 2
);
ctx.rotate(this.getRandomDeg());
ctx.scale(scaleBase, scaleBase);
ctx.textBaseline = "middle";
ctx.fillText(str[i], 0, 0);
ctx.restore();
ctx.save();
}
},
updateCanvas() {
if (!this.clickUpdate) return;
const ctx = this.ctx;
const ramdomStr = this.getRandomStr();
ctx.clearRect(0, 0, this.computedWidth, this.computedHeight);
this.initCanvas();
this.setCanvas(ramdomStr);
},
getRandomDeg() {
return (Math.PI / 180) * (-45 + Math.random() * 90);
},
getRandomRgb() {
return `rgb(${Math.floor(Math.random() * 255)},${Math.floor(
Math.random() * 255
)},${Math.floor(Math.random() * 255)})`;
},
setFont() {
let fontsize = this.computedWidth / (this.nums * 1.1);
if (fontsize >= this.computedHeight) {
fontsize = this.computedHeight * 0.8;
}
return fontsize;
},
},
};
</script>
组件参数
## 属性
value:图形验证码内容(由后端提供时填写)
nums: 验证码长度(number),默认:4
width: 图形验证码宽度(number)
height: 图形验证码高度(number)
color: 图形验证码内容颜色(string)
fillStyle:图形验证码填充颜色(string)
randomLine:是否开启随机干扰线条(boolean)
clickUpdate:是否开启点击更新图形验证码(boolean)
## 事件
getImgCode: 获取图形验证码内容
效果
?
?
?
|