Skip to content

FxCaptchaPointSelect 点选验证 ​

在验证码图片上按提示顺序点击目标文字位置,点击落点以带序号的圆标标注;点击最后一个已点的位置可倒序撤销重选(只能倒着清,不可跳删中间点)。真实点选的图为目标字与干扰字混排(只点提示指定的目标字,点到干扰字即失败),底部支持提示文本或提示图片,confirm 事件携带坐标序列(序号 + 容器内像素坐标 + 时间戳)交服务端校验。

演示可真点

下面演示的验证码图为内联 SVG 动态生成:「伏 羲 氏」三个目标字 + 3 个随机干扰字混排(同样式,注意区分)。按提示顺序点对三个目标字后点「确认」提示通过;点到干扰字、多点或少点都会判定失败并自动换一题。

vue
<script setup lang="ts">
import { ref } from "vue"
import { FxCaptchaPointSelect } from "@fx/components"
import type { CaptchaPoint } from "@fx/components"

// 目标字 + 干扰字(真实场景由服务端生成:图里混排、答案在服务端)
const TARGETS = ["伏", "羲", "氏"]
const DISTRACTORS = "风花雪月山水人间夜雨春秋星辰天地".split("")
const IMAGE_W = 320
const IMAGE_H = 200

const chars = ref<Array<{ char: string; x: number; y: number; isTarget: boolean }>>([])
const demoImage = ref("")

// 生成验证码图:目标字与干扰字随机混排 + 干扰线(演示用 SVG,真实场景为服务端图片)
function regenerate() {
  const slots = [
    { x: 12, y: 22 }, { x: 45, y: 60 }, { x: 82, y: 28 },
    { x: 22, y: 68 }, { x: 62, y: 18 }, { x: 85, y: 66 },
  ].sort(() => Math.random() - 0.5)
  const pool = [...DISTRACTORS].sort(() => Math.random() - 0.5)
  chars.value = [
    ...TARGETS.map((char, i) => ({ char, ...slots[i], isTarget: true })),
    ...pool.slice(0, 3).map((char, i) => ({ char, ...slots[3 + i], isTarget: false })),
  ]
  const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${IMAGE_W}" height="${IMAGE_H}">
    <rect width="100%" height="100%" fill="#1e293b"/>
    ${chars.value.map((c, i) =>
      `<text x="${(c.x / 100) * IMAGE_W}" y="${(c.y / 100) * IMAGE_H}" font-size="26"
        fill="#e2e8f0" text-anchor="middle">${c.char}</text>`).join("")}
  </svg>`
  demoImage.value = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`
}

regenerate()

// confirm 校验:点数须与目标字数一致,且第 i 次点击落在第 i 个目标字框内
const onConfirm = (points: CaptchaPoint[], clear: () => void) => {
  const targets = chars.value.filter((c) => c.isTarget)
  const pass =
    points.length === targets.length &&
    points.every((p, i) => {
      const b = targets[i]
      return (
        Math.abs((p.x / IMAGE_W) * 100 - b.x) < 8 &&
        Math.abs((p.y / IMAGE_H) * 100 - b.y) < 12
      )
    })
  if (pass) {
    window.alert("点选校验通过")
  } else {
    window.alert("点选校验失败,已换一题")
    clear()
    regenerate()
  }
}
</script>

<template>
  <FxCaptchaPointSelect
    :captcha-image="demoImage"
    hint-text="伏, 羲, 氏"
    :max="3"
    show-confirm
    @refresh="regenerate"
    @confirm="onConfirm"
  />
</template>

真实接入

真实场景验证码图与答案由服务端生成下发(目标字 + 干扰字 + 干扰线/扭曲),前端只负责采集点击坐标并在 confirm 里提交;max 设为目标字数实现定长点选,坐标按图片原始尺寸做比例换算。

Attributes ​

参数说明类型默认值
captchaImage验证码图片地址string—
width / height图片宽高(px 或 css 单位)number | string320 / 200
paddingX / paddingY卡片水平/垂直内边距(px)number12 / 16
title标题string'请按图依次点击'
hintText底部提示文本string—
hintImage底部提示图片(优先于 hintText)string—
showConfirm是否展示确认按钮booleanfalse
max最多可点选的点位数(达到后忽略点击;配合定长校验。showConfirm 时点满前确认按钮禁用,captchaImage 变化自动清空已点标记,与已点圆标间距过小的重复点击忽略)number—

Slots ​

插槽说明
title标题栏(默认标题文字)
extra标题栏右侧(默认刷新按钮)
footer底部(默认提示文本/提示图片)

Events ​

事件名说明回调参数
click单次点击(point: CaptchaPoint)
confirm确认(需 showConfirm)(points: CaptchaPoint[], clear: () => void)
refresh点击刷新(圆标已自动清空,换图由消费方处理)—

组合形态 ​

卡片容器独立导出为 FxCaptchaPointSelectCard(PointSelectionCaptchaCardProps:captchaImage / width / height / paddingX / paddingY / title + title/extra/default/footer 插槽 + click 事件),需要自绘点选逻辑时可直接组合卡片,完整点选能力用 FxCaptchaPointSelect。