基於canvas的數字/數字+字符驗證碼 SIdentify.vue 組件

<!-- 基於canvas的數字/數字+字符驗證碼 --> <!-- 調用格式 <s-identify @func="getMsgFormSon" :isRefreshCode="isRefreshCode" :identifyCodes="identifyCodes" //可選傳,選傳寫法有要求 ></s-identify> --> <template> <div class="s-canvas"> <canvas id="s-canvas" :width="contentWidth" :height="contentHeight"></canvas> </div> </template> <script> export default { name: "SIdentify", props: { isRefreshCode: { type: Boolean, default: false }, identifyCodes: { type: Array }, identifyLen: { type: Number, default: 4 }, fontSizeMin: { type: Number, default: 16 }, fontSizeMax: { type: Number, default: 40 }, backgroundColorMin: { type: Number, default: 180 }, backgroundColorMax: { type: Number, default: 240 }, colorMin: { type: Number, default: 50 }, colorMax: { type: Number, default: 160 }, lineColorMin: { type: Number, default: 40 }, lineColorMax: { type: Number, default: 180 }, dotColorMin: { type: Number, default: 0 }, dotColorMax: { type: Number, default: 255 }, contentWidth: { type: Number, default: 112 }, contentHeight: { type: Number, default: 32 } }, data() { return { nums: [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "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" ], identifyText: "" }; }, methods: { // 生成一個隨機數 randomNum(min, max) { return Math.floor(Math.random() * (max - min) + min); }, // 生成一個隨機的顏色 randomColor(min, max) { let r = this.randomNum(min, max); let g = this.randomNum(min, max); let b = this.randomNum(min, max); return "rgb(" + r + "," + g + "," + b + ")"; }, // 繪制干擾線 drawLine(ctx) { for (let i = 0; i < 6; 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(); } }, // 繪制干擾點 drawDot(ctx) { for (let i = 0; i < 50; i++) { ctx.fillStyle = this.randomColor(0, 255); ctx.beginPath(); ctx.arc( this.randomNum(0, this.contentWidth), this.randomNum(0, this.contentHeight), 1, 0, * Math.PI ); ctx.fill(); } }, // 生成l長度的驗證碼 makeCode(o, l) { let identifyCodes = o; this.identifyText = ""; for (let i = 0; i < l; i++) { this.identifyText += identifyCodes[this.randomNum(0, identifyCodes.length)]; } }, // 驗證碼文本 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.identifyText.length + 1)); let y = this.randomNum(this.fontSizeMax, this.contentHeight - 5); var 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); }, // 驗證碼圖形 drawPic() { let identifyCodesArray = this.identifyCodes ? this.identifyCodes : this.nums; this.makeCode(identifyCodesArray, this.identifyLen); let identifyCode = ""; let canvas = document.getElementById("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); console.log(this.identifyText, "huizhi"); // 繪制文字 for (let i = 0; i < this.identifyLen; i++) { this.drawText(ctx, this.identifyText[i], i); identifyCode += this.identifyText[i]; } // for (let i = 0; i < this.identifyArray.length; i++) { // this.drawText(ctx, this.identifyArray[i], i); // } this.drawLine(ctx); this.drawDot(ctx); console.log(identifyCode, "要傳的值"); // 向父組件傳值 this.$emit("func", identifyCode); } }, watch: { if (this.isRefreshCode) { this.drawPic(); } }, mounted() { this.drawPic(); } }; </script> <style lang="scss" scoped> .s-canvas { height: 32px; canvas { margin-top: 1px; margin-left: 8px; } } </style>
父組件調用
①默認 數字+字母驗證碼 形式

<template> <div> <el-input v-model="verificationCode" placeholder="驗證碼" /> <div class="identify-code" @click="refreshCode"> <!--驗證碼組件--> <s-identify @func="getSidentifyCode" :isRefreshCode="isRefreshCode"></s-identify> </div> </div> </template> <script> import Vue from "vue"; import SIdentify from "./common/SIdentify"; export default { components: { SIdentify }, data() { return { verificationCode: "", identifyCode: "", isRefreshCode: false, }; }, created() { // this.refreshCode(); }, mounted() {}, watch: {}, methods: { refreshCode() { this.identifyCode = ""; this.isRefreshCode = true; //更改狀態--SIdentify組件中監聽該狀態 }, getSidentifyCode(data) { this.identifyCode = data; this.isRefreshCode = false; console.log(this.identifyCode, "接收到的code"); } } }; </script> <style lang="scss" scoped> .identify-code { display: inline-block; } } </style>
②通過傳 純數字 為數字驗證碼

<template> <div> <el-input v-model="verificationCode" placeholder="驗證碼" /> <div class="identify-code" @click="refreshCode"> <!--驗證碼組件--> <s-identify @func="getSidentifyCode" :isRefreshCode="isRefreshCode"></s-identify> </div> </div> </template> <script> import Vue from "vue"; import SIdentify from "./common/SIdentify"; export default { components: { SIdentify }, data() { return { verificationCode: "", identifyCodes: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], identifyCode: "", isRefreshCode: false, }; }, created() { this.refreshCode(); }, mounted() {}, watch: {}, methods: { refreshCode() { this.identifyCode = ""; this.isRefreshCode = true; //更改狀態--SIdentify組件中監聽該狀態 // 隨機排序 if (this.identifyCodes.length) { let tempCodesArray = this.identifyCodes.sort(function() { return Math.random() - 0.5; }); this.identifyCodes = tempCodesArray; } }, getSidentifyCode(data) { this.identifyCode = data; this.isRefreshCode = false; console.log(this.identifyCode, "接收到的code"); } } }; </script> <style lang="scss" scoped> .identify-code { display: inline-block; } } </style>
當用方式②時, SIdentify.vue 組件 可以略去 isRefreshCode的監聽判斷,改為監聽 identifyCodes
代碼段為

SIdentify.vue <script> export default { ... watch: { identifyCodes() { this.drawPic(); } //, // isRefreshCode() { // this.drawPic(); // } } }; </script> <style lang="scss" scoped> . . . </style>