<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      前端實現數字驗證碼

      ????? 寫在開頭

      點贊 + 收藏 === 學會??????

      該代碼的主要功能是生成一個圖形驗證碼,并將其繪制在HTML的<canvas>元素上。驗證碼由4個隨機數字組成,背景和文字顏色隨機生成,且文字有一定的旋轉角度,增加了識別的難度。

      核心邏輯

      • useImageVerify:這是一個Vue 3的Composition API函數,用于管理驗證碼的生成和繪制。它返回一個包含domRef(指向<canvas>元素的引用)、imgCode(生成的驗證碼字符串)、setImgCode(設置驗證碼的函數)和getImgCode(重新生成驗證碼的函數)的對象。

      • randomNum:生成指定范圍內的隨機整數。

      • randomColor:生成指定范圍內的隨機RGB顏色。

      • draw:在<canvas>上繪制驗證碼。包括以下步驟:

        • 填充背景色。
        • 繪制4個隨機數字,每個數字有不同的字體大小和旋轉角度。
        • 繪制5條隨機干擾線。
        • 繪制41個隨機干擾點。

      實現細節

      • 隨機性:通過randomNumrandomColor函數確保驗證碼的每個部分(數字、顏色、旋轉角度等)都是隨機的。
      • Canvas繪制:使用Canvas API進行繪制,包括fillRectfillTextstrokearc等方法。
      • Vue生命周期:在onMounted鉤子中調用getImgCode,確保在組件掛載后立即生成驗證碼。

      擴展性

      • 可以通過修改NUMBER_STRING來支持更多字符(如字母)。
      • 可以通過調整randomNumrandomColor的參數來改變驗證碼的樣式和復雜度。

      使用場景

      • 該驗證碼生成函數適用于需要簡單圖形驗證碼的場景,如登錄、注冊等表單驗證。
      import { ref, onMounted } from "vue";
      
      /**
       * 繪制圖形驗證碼
       * @param width - 圖形寬度
       * @param height - 圖形高度
       */
      export const useImageVerify = (width = 120, height = 40) => {
        const domRef = ref<HTMLCanvasElement>();
        const imgCode = ref("");
      
        function setImgCode(code: string) {
          imgCode.value = code;
        }
      
        function getImgCode() {
          if (!domRef.value) return;
          imgCode.value = draw(domRef.value, width, height);
        }
      
        onMounted(() => {
          getImgCode();
        });
      
        return {
          domRef,
          imgCode,
          setImgCode,
          getImgCode
        };
      };
      
      function randomNum(min: number, max: number) {
        const num = Math.floor(Math.random() * (max - min) + min);
        return num;
      }
      
      function randomColor(min: number, max: number) {
        const r = randomNum(min, max);
        const g = randomNum(min, max);
        const b = randomNum(min, max);
        return `rgb(${r},${g},${b})`;
      }
      
      function draw(dom: HTMLCanvasElement, width: number, height: number) {
        let imgCode = "";
      
        const NUMBER_STRING = "0123456789";
      
        const ctx = dom.getContext("2d");
        if (!ctx) return imgCode;
      
        ctx.fillStyle = randomColor(180, 230);
        ctx.fillRect(0, 0, width, height);
        for (let i = 0; i < 4; i += 1) {
          const text = NUMBER_STRING[randomNum(0, NUMBER_STRING.length)];
          imgCode += text;
          const fontSize = randomNum(18, 41);
          const deg = randomNum(-30, 30);
          ctx.font = `${fontSize}px Simhei`;
          ctx.textBaseline = "top";
          ctx.fillStyle = randomColor(80, 150);
          ctx.save();
          ctx.translate(30 * i + 15, 15);
          ctx.rotate((deg * Math.PI) / 180);
          ctx.fillText(text, -15 + 5, -15);
          ctx.restore();
        }
        for (let i = 0; i < 5; i += 1) {
          ctx.beginPath();
          ctx.moveTo(randomNum(0, width), randomNum(0, height));
          ctx.lineTo(randomNum(0, width), randomNum(0, height));
          ctx.strokeStyle = randomColor(180, 230);
          ctx.closePath();
          ctx.stroke();
        }
        for (let i = 0; i < 41; i += 1) {
          ctx.beginPath();
          ctx.arc(randomNum(0, width), randomNum(0, height), 1, 0, 2 * Math.PI);
          ctx.closePath();
          ctx.fillStyle = randomColor(150, 200);
          ctx.fill();
        }
        return imgCode;
      }

      vue頁面使用

      <script setup lang="ts">
      import { watch } from "vue";
      import { useImageVerify } from "./hooks";
      
      defineOptions({
        name: "ReImageVerify"
      });
      
      interface Props {
        code?: string;
      }
      
      interface Emits {
        (e: "update:code", code: string): void;
      }
      
      const props = withDefaults(defineProps<Props>(), {
        code: ""
      });
      
      const emit = defineEmits<Emits>();
      
      const { domRef, imgCode, setImgCode, getImgCode } = useImageVerify();
      
      watch(
        () => props.code,
        newValue => {
          setImgCode(newValue);
        }
      );
      watch(imgCode, newValue => {
        emit("update:code", newValue);
      });
      
      defineExpose({ getImgCode });
      </script>
      
      <template>
        <canvas
          ref="domRef"
          width="120"
          height="40"
          class="cursor-pointer"
          @click="getImgCode"
        />
      </template>

      如果對您有所幫助,歡迎您點個關注,我會定時更新技術文檔,大家一起討論學習,一起進步。

      posted @ 2025-06-05 18:37  林恒  閱讀(199)  評論(1)    收藏  舉報
      主站蜘蛛池模板: 亚洲欧美日韩综合久久久| 少妇被粗大的猛烈进出视频| 91人妻熟妇在线视频| 人人爽人人爽人人片a免费| 午夜福利宅福利国产精品| 亚洲一区二区av免费| 五月天中文字幕mv在线| 国产按头口爆吞精在线视频| 亚洲国产av无码精品无广告 | 久久亚洲精品11p| 深夜精品免费在线观看| 亚洲综合一区二区三区不卡| 公天天吃我奶躁我的在线观看| 在线观看美女网站大全免费| 18禁网站免费无遮挡无码中文 | 国产精品亚欧美一区二区三区| 苍井空一区二区三区在线观看| 国产午夜精品视频在线播放| 精品国产亚洲一区二区三区| 国产精品成人久久电影| 少妇扒开双腿自慰出白浆| 凤翔县| 久久精品麻豆日日躁夜夜躁| 不卡国产一区二区三区| 津南区| 久久伊99综合婷婷久久伊| 福利视频在线播放| 亚洲欧洲日产国码久在线| 亚洲综合国产激情另类一区| 亚洲av成人网人人蜜臀| 国产一区二区三区av在线无码观看| 乌克兰美女浓毛bbw| 久久一级精品久熟女人妻| 91中文字幕一区二区| 疏附县| 国产偷窥熟女高潮精品视频 | 正在播放肥臀熟妇在线视频| 亚洲精品一区二区妖精| 天天摸夜夜摸夜夜狠狠添| 成人国产精品日本在线观看| 久久精品夜色国产亚洲av|