CaptchaCanvas.vue 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. <template>
  2. <div class="cap-wrap" @click="refresh" :title="'点击刷新验证码'">
  3. <canvas ref="cv" :width="w" :height="h"></canvas>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "CaptchaCanvas",
  9. props: { value: String, w: { type: Number, default: 173 }, h: { type: Number, default: 64 } },
  10. data() { return { code: "" }; },
  11. mounted() { this.refresh(); },
  12. methods: {
  13. randChar() {
  14. const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
  15. return chars[Math.floor(Math.random() * chars.length)];
  16. },
  17. refresh() {
  18. this.code = Array.from({ length: 4 }).map(() => this.randChar()).join("");
  19. this.$emit("input", this.code);
  20. const cv = this.$refs.cv;
  21. const ctx = cv.getContext("2d");
  22. // 背景
  23. ctx.clearRect(0, 0, this.w, this.h);
  24. const g = ctx.createLinearGradient(0, 0, this.w, this.h);
  25. g.addColorStop(0, "rgba(14,45,120,0.65)");
  26. g.addColorStop(1, "rgba(8,20,55,0.85)");
  27. ctx.fillStyle = g;
  28. ctx.fillRect(0, 0, this.w, this.h);
  29. // 干扰线
  30. for (let i = 0; i < 5; i++) {
  31. ctx.strokeStyle = `rgba(60,180,255,${0.15 + Math.random()*0.25})`;
  32. ctx.beginPath();
  33. ctx.moveTo(Math.random() * this.w, Math.random() * this.h);
  34. ctx.lineTo(Math.random() * this.w, Math.random() * this.h);
  35. ctx.stroke();
  36. }
  37. // 字符
  38. ctx.font = "bold 22px Arial";
  39. ctx.textBaseline = "middle";
  40. for (let i = 0; i < this.code.length; i++) {
  41. const x = 22 + i * 32;
  42. const y = this.h / 2 + (Math.random() * 6 - 4);
  43. ctx.save();
  44. ctx.translate(x, y);
  45. ctx.rotate((Math.random() * 14 - 7) * Math.PI / 180);
  46. ctx.fillStyle = "rgba(210,245,255,0.92)";
  47. ctx.fillText(this.code[i], -8, 0);
  48. ctx.restore();
  49. }
  50. }
  51. }
  52. };
  53. </script>
  54. <style scoped>
  55. .cap-wrap{
  56. width: 165px;
  57. height: 54px;
  58. border: 1px solid #3D6EB8;
  59. border-radius: 8px;
  60. overflow: hidden;
  61. cursor: pointer;
  62. }
  63. canvas{ display:block; }
  64. </style>