🎯 滑块验证组件 (Slider Captcha)

一个现代化、响应式的滑块验证组件,专为 React 应用设计,提供流畅的用户体验和强大的安全验证功能。

✨ 功能特性

🎮 核心功能

  • 智能滑块拖拽 – 支持鼠标和触摸屏操作,响应灵敏
  • 随机目标位置 – 每次验证生成不同的目标位置,提高安全性
  • 实时位置验证 – 精确的位置检测,支持容错范围设置
  • 状态反馈 – 清晰的视觉反馈,包括成功、错误和待验证状态

🎨 用户体验

  • 流畅动画 – 平滑的过渡动画和微交互效果
  • 响应式设计 – 完美适配桌面端和移动端
  • 直观界面 – 简洁美观的 UI 设计,操作简单明了
  • 即时反馈 – 实时显示验证状态和结果

🔧 技术特性

  • React Hooks – 使用最新的 React Hooks API
  • TypeScript 支持 – 完整的类型定义(可扩展)
  • Tailwind CSS – 现代化的样式框架
  • 事件处理 – 完善的鼠标和触摸事件处理
  • 性能优化 – 使用 useCallback 优化事件处理函数

🌟 产品亮点

  • 拖拽体验 – 滑块跟随鼠标/手指移动,提供真实的拖拽感
  • 视觉引导 – 绿色指示器显示目标位置,用户一目了然
  • 状态动画 – 成功时的庆祝动画,错误时的震动反馈
  • 触摸支持 – 完美支持移动端触摸操作
  • 响应式布局 – 自适应不同屏幕尺寸
  • 浏览器兼容 – 支持主流浏览器

🎯 使用场景

1. 用户注册/登录

  • 防止机器人注册 – 在用户注册时验证人类用户
  • 登录安全 – 在敏感操作前进行身份验证
  • 密码重置 – 重置密码流程中的安全验证

2. 表单提交

  • 评论系统 – 防止垃圾评论和恶意提交
  • 联系表单 – 保护网站免受垃圾邮件攻击
  • 调查问卷 – 确保问卷数据的真实性

3. 内容保护

  • 下载验证 – 下载敏感文件前的身份验证
  • 内容访问 – 访问付费或限制内容前的验证
  • API 调用 – 防止 API 接口被恶意调用

4. 电商应用

  • 下单验证 – 防止恶意下单和刷单行为
  • 优惠券领取 – 限制优惠券的领取频率
  • 评价系统 – 确保评价的真实性

5. 管理后台

  • 敏感操作 – 管理员执行危险操作前的确认
  • 数据导出 – 导出大量数据前的安全验证
  • 系统设置 – 修改关键系统设置时的验证

🚀 快速开始

使用组件

import SliderCaptcha from "./components/SliderCaptcha";function App() {return (<div className="App"><SliderCaptcha /></div>);
}

自定义配置

// 可以轻松扩展组件以支持自定义配置
const captchaConfig = {tolerance: 15, // 容错范围sliderWidth: 40, // 滑块宽度trackHeight: 48, // 轨道高度theme: "dark", // 主题样式
};

源码

import { useState, useRef, useEffect, useCallback } from "react";export default function SliderCaptcha() {const [isVerified, setIsVerified] = useState(false);const [isDragging, setIsDragging] = useState(false);const [sliderPosition, setSliderPosition] = useState(0);const [startX, setStartX] = useState(0);const [targetPosition, setTargetPosition] = useState(0);const [showSuccess, setShowSuccess] = useState(false);const [showError, setShowError] = useState(false);const sliderRef = useRef(null);const trackRef = useRef(null);const containerRef = useRef(null);// 生成随机目标位置useEffect(() => {const container = containerRef.current;if (container) {const containerWidth = container.offsetWidth;const sliderWidth = 32; // 滑块宽度 (w-8 = 32px)const maxPosition = containerWidth - sliderWidth;const randomPosition = Math.random() * (maxPosition - 50) + 25; // 避免太靠近边缘setTargetPosition(randomPosition);}}, []);// 获取客户端坐标const getClientX = useCallback((e) => {return e.touches ? e.touches[0].clientX : e.clientX;}, []);// 鼠标/触摸事件处理const handleStart = useCallback((e) => {if (isVerified) return;e.preventDefault();setIsDragging(true);setStartX(getClientX(e) - sliderPosition);setShowError(false);},[isVerified, sliderPosition, getClientX]);const handleMove = useCallback((e) => {if (!isDragging || isVerified) return;e.preventDefault();const container = containerRef.current;if (!container) return;const containerWidth = container.offsetWidth;const sliderWidth = 32;const maxPosition = containerWidth - sliderWidth;let newPosition = getClientX(e) - startX;newPosition = Math.max(0, Math.min(newPosition, maxPosition));setSliderPosition(newPosition);},[isDragging, isVerified, startX, getClientX]);const handleEnd = useCallback(() => {if (!isDragging || isVerified) return;setIsDragging(false);// 验证滑块位置const tolerance = 10; // 允许的误差范围const isCorrect = Math.abs(sliderPosition - targetPosition) <= tolerance;if (isCorrect) {setIsVerified(true);setShowSuccess(true);setTimeout(() => setShowSuccess(false), 2000);} else {setShowError(true);// 重置滑块位置setTimeout(() => {setSliderPosition(0);setShowError(false);}, 1000);}}, [isDragging, isVerified, sliderPosition, targetPosition]);// 重置验证const handleReset = () => {setIsVerified(false);setIsDragging(false);setSliderPosition(0);setShowSuccess(false);setShowError(false);// 重新生成目标位置const container = containerRef.current;if (container) {const containerWidth = container.offsetWidth;const sliderWidth = 32;const maxPosition = containerWidth - sliderWidth;const randomPosition = Math.random() * (maxPosition - 50) + 25;setTargetPosition(randomPosition);}};// 添加全局鼠标/触摸事件监听useEffect(() => {if (isDragging) {document.addEventListener("mousemove", handleMove);document.addEventListener("mouseup", handleEnd);document.addEventListener("touchmove", handleMove, { passive: false });document.addEventListener("touchend", handleEnd);return () => {document.removeEventListener("mousemove", handleMove);document.removeEventListener("mouseup", handleEnd);document.removeEventListener("touchmove", handleMove);document.removeEventListener("touchend", handleEnd);};}}, [isDragging, handleMove, handleEnd]);return (<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center p-4"><div className="bg-white rounded-2xl shadow-xl p-8 max-w-md w-full"><h2 className="text-2xl font-bold text-gray-800 mb-6 text-center">滑块验证</h2><div className="mb-6"><p className="text-gray-600 text-center mb-4">{isVerified ? "✅ 验证成功!" : "请将滑块拖拽到正确位置完成验证"}</p></div>{/* 验证区域 */}<divref={containerRef}className="relative bg-gray-100 rounded-lg h-12 mb-6 overflow-hidden">{/* 背景图片或图案 */}<div className="absolute inset-0 bg-gradient-to-r from-blue-200 to-purple-200 opacity-30"></div>{/* 目标位置指示器 */}<divclassName="absolute top-1 bottom-1 w-2 bg-green-600 rounded-lg shadow ring-2 ring-green-300 transition-opacity duration-300"style={{left: `${targetPosition}px`,opacity: isVerified ? 0 : 1,}}></div>{/* 滑块轨道 */}<divref={trackRef}className="absolute top-0 bottom-0 left-0 bg-blue-500 transition-all duration-300 ease-out"style={{width: `${sliderPosition}px`,opacity: isVerified ? 0.8 : 0.6,}}></div>{/* 滑块 */}{!isVerified && (<divref={sliderRef}className={`absolute top-1 bottom-1 w-8 bg-white rounded-md shadow-lg cursor-pointer transition-all duration-200 ease-out flex items-center justify-center${isDragging ? "shadow-xl scale-105" : ""}hover:shadow-lg${showError ? "animate-shake" : ""}`}style={{ left: `${sliderPosition}px` }}onMouseDown={handleStart}onTouchStart={handleStart}><svgclassName="w-4 h-4 text-gray-500"fill="currentColor"viewBox="0 0 20 20"><pathfillRule="evenodd"d="M10.293 3.293a1 1 0 011.414 0l6 6a1 1 0 010 1.414l-6 6a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-4.293-4.293a1 1 0 010-1.414z"clipRule="evenodd"/></svg></div>)}{/* 成功提示 */}{showSuccess && (<div className="absolute inset-0 bg-green-500 bg-opacity-20 flex items-center justify-center"><div className="bg-white rounded-lg px-4 py-2 shadow-lg"><span className="text-green-600 font-semibold">验证成功!</span></div></div>)}{/* 错误提示 */}{showError && (<div className="absolute inset-0 bg-red-500 bg-opacity-20 flex items-center justify-center"><div className="bg-white rounded-lg px-4 py-2 shadow-lg"><span className="text-red-600 font-semibold">位置错误,请重试</span></div></div>)}</div>{/* 操作按钮 */}<div className="flex gap-4"><buttononClick={handleReset}className="flex-1 bg-gray-500 hover:bg-gray-600 text-white font-semibold py-3 px-6 rounded-lg transition-colors duration-200">重置验证</button>{isVerified && (<buttononClick={() => alert("验证通过,可以继续操作!")}className="flex-1 bg-green-500 hover:bg-green-600 text-white font-semibold py-3 px-6 rounded-lg transition-colors duration-200">继续</button>)}</div>{/* 状态指示器 */}<div className="mt-4 text-center"><div className="inline-flex items-center gap-2 px-3 py-1 rounded-full text-sm">{isVerified ? (<><div className="w-2 h-2 bg-green-500 rounded-full"></div><span className="text-green-600">已验证</span></>) : (<><div className="w-2 h-2 bg-yellow-500 rounded-full animate-pulse"></div><span className="text-yellow-600">待验证</span></>)}</div></div></div></div>);
}

 React 极简响应式滑块验证组件实现,随机滑块位置 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿动态资讯

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/913363.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/913363.shtml
英文地址,请注明出处:http://en.pswp.cn/news/913363.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32第十六天蓝牙模块

一&#xff1a;蓝牙模块HC-05 1&#xff1a;硬件引脚配置&#xff1a; | 标号 | PIN | 说明 | |------|-------|---------------------------------------| | 1 | START | 状态引出引脚&#xff08;未连接/连接输出信号时&#xff09; |…

时序数据库IoTDB用户自定义函数(UDF)使用指南

1. 编写UDF时序数据库IoTDB为用户提供了编写UDF的JAVA API&#xff0c;用户可以自主实现UDTF&#xff08;用户自定义转换函数&#xff09;类&#xff0c;IoTDB将通过类加载机制装载用户编写的类。Maven依赖如果使用Maven&#xff0c;可以从Maven库中搜索以下依赖&#xff0c;并…

Linux国产与国外进度对垒

Linux国产与国外进度对垒 引言国产Linux的发展现状国外Linux的发展现状技术对比国产Linux的挑战与机遇国外Linux的优势与局限结论 引言 简述Linux在全球操作系统市场中的地位国产Linux的发展背景与意义国外主流Linux发行版的现状 国产Linux的发展现状 主要国产Linux发行版介…

Jenkins-Email Extension 插件插件

Editable Email Notification Editable Email Notification 是 Jenkins 的 Email Extension 插件的核心功能&#xff0c;用于自定义邮件通知&#xff0c;包括邮件主题、内容、收件人、发件人等 属性 1.Project From 项目发件人&#xff0c;设置邮件的发件人地址 **注意&…

windows系统下将Docker Desktop安装到除了C盘的其它盘中

windows系统下安装docker会自动安装到C盘&#xff0c;可以采用下面的方法将其安装到其它盘中1、先下载Docker Desktop安装程序Docker Desktop Installer.exe&#xff0c;比如你下载到了C:\Users\YourUsername\Downloads 文件夹中。 2、打开 PowerShell 进入C:\Users\YourUser…

视频工具箱 1.1.1 |小而美的视频处理工具,支持多种常用功能

VideoTools是一款基于FFmpeg的小而美的视频处理工具&#xff0c;专为需要快速高效地进行视频编辑的用户设计。这款工具无需安装&#xff0c;体积仅约200KB&#xff0c;提供了视频压缩、格式转换、转GIF、修改分辨率、加速播放以及音频提取等多种常用功能。其用户界面简洁直观&a…

无人机集群搜索技术全面解析

无人机集群搜索是指通过多架无人机协同工作&#xff0c;实现对目标区域的高效覆盖与快速探测。这项技术通过模拟自然界生物群体的集体行为&#xff0c;利用分布式控制和自主决策算法&#xff0c;使无人机集群能够自组织地完成复杂搜索任务。下面从核心技术、应用场景、算法实现…

【Elasticsearch】深度分页及其替代方案

深度分页及其替代方案 1.深度分页2.为什么不推荐深度分页2.1 性能问题&#xff08;核心原因&#xff09;2.2 资源消耗对比2.3 实际限制 3.深度分页的替代方案3.1 方案一&#xff1a;Search After&#xff08;推荐&#xff09;3.1.1 为什么 Search After 性能更高3.1.2 技术原理…

论文阅读笔记——VGGT: Visual Geometry Grounded Transformer

VGGT 论文 输入是 N 个 RGB 图像 I i ∈ R 3 H W I_i\in\mathbb{R}^{3HW} Ii​∈R3HW 的序列 ( I i ) i 1 N (I_i)^N_{i1} (Ii​)i1N​&#xff0c;观察相同 3D 场景。 VGGT 的 Transformer 是一个映射函数&#xff0c;将此序列映射为一组对应的 3D 标注&#xff0c; f ( …

【嵌入式电机控制#11】PID控制入门:对比例算法应用的深度理解

接下来内容需要数学功底&#xff0c;并且有现成结论的内容不做推导&#xff0c;重在讲解工程实践中的方法论&#xff0c;建议控制类专业或学习过相关理论的人阅读 一、开闭环系统 &#xff08;1&#xff09;开环控制系统&#xff1a;被控对象输出对控制器的输出没有影响 &…

多视图几何:本质矩阵与基础矩阵

文章目录 1. 前置知识1.1. 向量叉乘1.2. 混合积1.3. 引理证明 2. 本质矩阵3. 基础矩阵4. 应用例子 1. 前置知识 1.1. 向量叉乘 假设 a ( a x a y a z ) \mathbf{a} \begin{pmatrix} a_x \\ a_y \\ a_z \end{pmatrix} a ​ax​ay​az​​ ​ 以及 b ( b x b y b z ) \mat…

Hive集群之间迁移的Linux Shell脚本

新旧 Hive 集群之前数据迁移单表脚本 migrate_hive_single_table.sh #!/bin/bash#配置参数 OLD_NAMENODE"hdfs://<old-namenode>:<old-port>" EXPORT_PATH"/tmp/hive-export/dm" NEW_DB"dm_events" TABLE_NAME"dm_usereventfi…

新时代的开始,华为开源仓颉编程语言!

7月30日&#xff0c;华为即将开源自研的仓颉编程语言。 仓颉这个名字很有意思。传说中的仓颉创造了汉字&#xff0c;开启了中华文明的文字时代。华为用这个名字&#xff0c;体现了对中华文化的致敬。从2020年开始研发&#xff0c;到去年首次亮相&#xff0c;再到现在的全面开源…

【python实用小脚本-128】基于 Python 的 Hacker News 爬虫工具:自动化抓取新闻数据

引言 在技术社区中&#xff0c;Hacker News 是一个汇聚最新技术文章和讨论的热门平台。许多开发者和技术爱好者依赖它来获取行业动态和前沿资讯。然而&#xff0c;手动浏览和筛选这些文章可能耗时且低效。本文将介绍一个基于 Python 的 Hacker News 爬虫工具&#xff0c;它能够…

mac 电脑安装Homebrew来安装npm与node成功后,安装nvm的流程

文章目录 前言一、卸载node(如果没下载可以忽略这步)1.官网下载安装包的2. homebrew安装的 二、安装Homebrew(1) 命令安装&#xff08;2&#xff09;出现上面提示&#xff0c;执行对应的命令&#xff08;3&#xff09;校验是否安装成功 三&#xff1a;安装node&#xff08;Home…

根据无人机倾斜摄影osgb做的3dmax模型3dtiles制作,导出.b3dm加载到谷歌地图cesiumlab

根据无人机倾斜摄影osgb做的3dmax模型3dtiles制作&#xff0c;导出.b3dm加载到谷歌地图cesiumlab 根据无人机倾斜摄影osgb做的3dmax模型3dtiles制作&#xff0c;导出.b3dm加载到谷歌地图cesiumlab

Yocto项目:嵌入式Linux开发的“万能烹饪手册”

目录 一.Yocto是什么? 二.Yocto如何运作&#xff1f; 2.1 三大核心工具 2.2 实例 三.为什么开发者爱用Yocto&#xff1f; 3.1 ​自由定制&#xff0c;拒绝“全家桶”​​ 3.2 跨平台支持&#xff1a;从x86到火星芯片​ 3.3 工业级可靠性​ PetaLinux是Xilinx官方推出的…

【nosql】有哪些非关系型数据库?

非关系型数据库Nosql 分类 键值存储 (Key-Value Store): 代表: Redis, DynamoDB, RocksDB, etcd核心优势: 极致简单、超高读写性能&#xff08;尤其内存型&#xff09;、高吞吐。场景: 缓存、会话存储、配置、计数器、分布式协调、简单消息队列。 列式 / 宽列存储 (Wide-Colu…

Redis存储Cookie实现爬虫保持登录 requests | selenium

前言 前面已经介绍了requests和selenium这两种方式的基础知识和模拟登录,但是我们需要每次都进行登录,这明显是很麻烦并且不合理的,所以这次我分享一下怎么可以让我们的程序进行一次登录之后,和普通浏览器一样下次不进行登录直接进行对网站数据的爬取 下面的我分享的内容需要…

leetcode:474. 一和零[01背包][动态规划]

学习要点 给定背包容量&#xff0c;装满背包最多有多少个物品深入理解01背包深入理解动态规划 题目链接 474. 一和零 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法:01背包 class Solution { public:int findMaxForm(vector<string>& strs, int m, int …