---
title: SliderCaptcha 滑块验证码
description: 按住滑块拖到行内结束端完成验证,支持键盘操作与 RTL
---
# SliderCaptcha 滑块验证码
`SliderCaptcha` 是一个「按住滑块拖到最右端」的验证控件,`v-model` 绑 `boolean`,`true` 表示**已验证通过**。
## 何时使用
- 登录 / 注册 / 短信验证码等需要「一次人为停顿」的入口;
- 轻量混淆脚本、降低误触强度的场景;
- **不要**把它当安全边界:拖拽与键盘都能被脚本模拟,它能挡住的只是「顺手连点」,真正的风控要靠服务端。
## 基础用法
`v-model` 绑 `boolean`;`success` 在通过的那一刻触发一次,方便埋点或联动下一步。
`text` / `successText` 可覆盖语言包文案(默认取 `captcha` 语言包分组)。
## 尺寸
`size` 取 `small` / `medium` / `large`,高度分别跟随 `--g3-control-height-sm` / `--g3-control-height` / `--g3-control-height-lg`;手柄是正方形,宽度自动等于高度。
## 与表单一起使用
放进 `G3FormItem` 时,label 与校验交给表单,滑块只负责提供值。验证是有状态的,**每轮提交都要复位**:清掉绑定值后调 `resume()`,让用户重新拖一次。
## 键盘与无障碍
手柄是 `role="slider"`,带 `aria-valuemin` / `aria-valuemax` / `aria-valuenow`(0~100 的完成度)与 `aria-valuetext`(当前提示文案,通过后是成功文案),读屏可直接播报状态。
| 按键 | 行为 |
| --- | --- |
| `Tab` | 聚焦手柄(未通过时才可聚焦,通过后 `tabindex="-1"`) |
| `→` / `↑` | 沿屏幕上「向右」推进一档(行程的 1/10,最少 20px) |
| `←` / `↓` | 回退一档 |
| `Home` | 回到起点(不复位通过状态) |
| `End` | 直达终点并通过验证 |
`keyboard={false}` 可关掉键盘通道(只保留指针拖拽)。
## RTL
位置用逻辑属性 `inset-inline-start` 表达,镜像由 `dir` 自动完成:RTL 下手柄从**右侧**起步、向**左**拖到终点。指针位移按行内方向折算(`useDirection`),方向键的左右也随方向翻转 —— 对用户而言始终是「朝屏幕上那个方向推到底」。
## API
### Props
| 名称 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
| `modelValue` | `boolean` | `false` | 双向绑定:是否已验证通过 |
| `text` | `string` | 语言包 | 未通过时的提示文案 |
| `successText` | `string` | 语言包 | 通过后的文案 |
| `disabled` | `boolean` | `false` | 禁用态:不响应拖拽与键盘(样式不作整体半透明) |
| `size` | `'small' \| 'medium' \| 'large'` | `'medium'` | 尺寸 |
| `keyboard` | `boolean` | `true` | 是否支持键盘操作 |
### Events
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `update:modelValue` | `(value: boolean)` | 验证状态变化 |
| `success` | `({ isPassing: true })` | 通过时触发一次 |
| `start` | `(event: PointerEvent)` | 开始拖拽 |
| `move` | `({ event, moveDistance, offset })` | 拖拽过程中触发(键盘操作不触发) |
| `end` | `(event: PointerEvent)` | 拖拽结束(含取消) |
### Slots
| 名称 | 参数 | 说明 |
| --- | --- | --- |
| `text` | `{ isPassing }` | 覆盖提示文案 |
| `action` | `{ isPassing }` | 覆盖手柄里的图标(默认 `ChevronsRight` / 通过后 `Check`,RTL 下由全库的图标镜像规则翻面) |
### 实例方法
| 名称 | 签名 | 说明 |
| --- | --- | --- |
| `resume` | `() => void` | 复位到未通过状态(清绑定值 + 回弹动画),校验失败后调用 |
### 类型定义
```ts
export type SliderCaptchaSize = 'small' | 'medium' | 'large'
export interface SliderCaptchaProps {
modelValue?: boolean
text?: string
successText?: string
disabled?: boolean
size?: SliderCaptchaSize
keyboard?: boolean
}
```
### 样式变量
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `--g3-control-height` | `32px` | 默认高度(手柄宽 = 高度) |
| `--g3-control-height-sm` | `24px` | `size="small"` 的高度 |
| `--g3-control-height-lg` | `40px` | `size="large"` 的高度 |
| `--g3-fill` | `rgba(0, 0, 0, 0.04)` | 轨道底色 |
| `--g3-border-color` | `#d9d9d9` | 轨道描边 |
| `--g3-color-success` | `hsl(144 57% 58%)` | 进度条与通过后的手柄图标色 |
| `--g3-bg-container` | `#fff` | 手柄底色 |
## 实现说明
- **拖拽走 Pointer Events + `setPointerCapture`**(与 `bindDrag` / `bindResize` 同一套):指针移出组件、触屏、手写笔都能正确收尾,不需要往 `document` 上挂全局监听;捕获失败的老环境会退化成「移出即松手」,不会卡住。
- **跟手不加过渡**:拖拽期间进度条与手柄必须实时跟随指针,只有回弹 / `Home` / `End` 跳转才启用 300ms 过渡(`is-returning`),否则会有「拖不动」的手感。
- **行程 = 容器宽 - 手柄宽**:每次交互开始时量一次 `getBoundingClientRect()`,因此容器宽度自适应、字体缩放、`size` 变化都不需要监听 resize。
- **只有从「已通过」回退时才 `emit('update:modelValue', false)`**:中途松手的回弹不该对外重复报一次 `false`。
- **文案不硬编码**:默认值来自语言包 `captcha.slide` / `captcha.verified` / `captcha.sliderLabel`。
- 初始 `modelValue = true`(回填已通过状态)时,手柄在挂载后一帧落到行程末端,不会停在起点。