| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- <template>
- <div class="cap-wrap" @click="refresh" :title="'点击刷新验证码'">
- <canvas ref="cv" :width="w" :height="h"></canvas>
- </div>
- </template>
- <script>
- export default {
- name: "CaptchaCanvas",
- props: { value: String, w: { type: Number, default: 173 }, h: { type: Number, default: 64 } },
- data() { return { code: "" }; },
- mounted() { this.refresh(); },
- methods: {
- randChar() {
- const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
- return chars[Math.floor(Math.random() * chars.length)];
- },
- refresh() {
- this.code = Array.from({ length: 4 }).map(() => this.randChar()).join("");
- this.$emit("input", this.code);
- const cv = this.$refs.cv;
- const ctx = cv.getContext("2d");
- // 背景
- ctx.clearRect(0, 0, this.w, this.h);
- const g = ctx.createLinearGradient(0, 0, this.w, this.h);
- g.addColorStop(0, "rgba(14,45,120,0.65)");
- g.addColorStop(1, "rgba(8,20,55,0.85)");
- ctx.fillStyle = g;
- ctx.fillRect(0, 0, this.w, this.h);
- // 干扰线
- for (let i = 0; i < 5; i++) {
- ctx.strokeStyle = `rgba(60,180,255,${0.15 + Math.random()*0.25})`;
- ctx.beginPath();
- ctx.moveTo(Math.random() * this.w, Math.random() * this.h);
- ctx.lineTo(Math.random() * this.w, Math.random() * this.h);
- ctx.stroke();
- }
- // 字符
- ctx.font = "bold 22px Arial";
- ctx.textBaseline = "middle";
- for (let i = 0; i < this.code.length; i++) {
- const x = 22 + i * 32;
- const y = this.h / 2 + (Math.random() * 6 - 4);
- ctx.save();
- ctx.translate(x, y);
- ctx.rotate((Math.random() * 14 - 7) * Math.PI / 180);
- ctx.fillStyle = "rgba(210,245,255,0.92)";
- ctx.fillText(this.code[i], -8, 0);
- ctx.restore();
- }
- }
- }
- };
- </script>
- <style scoped>
- .cap-wrap{
- width: 165px;
- height: 54px;
- border: 1px solid #3D6EB8;
- border-radius: 8px;
- overflow: hidden;
- cursor: pointer;
- }
- canvas{ display:block; }
- </style>
|