
滑块验证参考 https://www.jianshu.com/p/341843516639
https://github.com/menthe/unlock.js
https://blog.csdn.net/tel13259437538/article/details/79823112
https://blog.csdn.net/tel13259437538/article/details/79822694
图片验证码参考 https://segmentfault.com/a/1190000018309458
rc-slider-captcha
https://github.com/caijf/rc-slider-captcha
https://juejin.cn/post/7160519128950767652
pnpm add rc-slider-captcha
支持图片验证,滑块验证
SliderBlock

import React, {useEffect, useRef, useState, memo} from 'react';import PropTypes from 'prop-types';SliderBlock.propTypes = {onChange: PropTypes.func.isRequired,height: PropTypes.number,};SliderBlock.defaultProps = {height: 32,onChange: () => {},}function SliderBlock({height, onChange}) {const btnRef = useRef();const [title, setTitle] = useState('拖动滑块验证');const style = {height}useEffect(init, []);function init() {const $slider = btnRef.current;if (!$slider) return console.error('没有找到 _slider_ DOM');const $btn = $slider.querySelector('.button') // 滑块const $title = $slider.querySelector('.title') // 文字const $bg = $slider.querySelector('.success') // 背景颜色const MOVE_WIDTH = $slider.offsetWidth - $btn.offsetWidth; // 可以移动的距离// 触发事件 onmousedown按下 onmousemove移动 onmouseup松开$btn.onmousedown = (e) => {// e.clientX 鼠标点的位置onMouseMove(e.clientX)}// 鼠标松开时document.onmouseup = () => {if (parseInt($btn.style.left) === MOVE_WIDTH) return;// 松开后回到原点,清除移动事件$btn.style.left = 0$bg.style.width = 0document.onmousemove = null$title.classList.remove('white')}// 拖拽移动时发生function onMouseMove(clientX) {document.onmousemove = (e) => {e.preventDefault();// 移动的X轴坐标 = 当前的 clientX - 之前鼠标的 clientXconst moveX = e.clientX - clientX;// 可移动的范围 = 总宽度 - 按钮的宽度if (moveX >= 0 && moveX <= MOVE_WIDTH) {$btn.style.left = moveX + 'px' // 滑块绝对定位$bg.style.width = moveX + 'px' // 设备背景的宽度if (moveX > MOVE_WIDTH / 2) {$title.classList.add('white')}}// 验证成功if (moveX >= MOVE_WIDTH) {$btn.style.left = MOVE_WIDTH + 'px' // 滑块绝对定位$bg.style.width = MOVE_WIDTH + 'px' // 设备背景的宽度setTitle('验证成功')onChange(true)// 事件清除-按下、移动$btn.onmousedown = null$btn.onmouseup = nulldocument.onmousemove = null}}}}return (<divclassName="_slider_"ref={btnRef}style={style}><div className="button"/><span className="title">{title}</span><span className="success"/></div>);}export default memo(SliderBlock);
slider-block.less
.white {color: #fff;transition: color 0.3s linear;}._slider_ {display: flex;align-items: center;position: relative;width: 100%;height: 32px;background: #fafafa;user-select:none;.button {position: absolute;left: 0;top: 0;width: 40px;height: 100%;border: 1px solid #dedede;color: rgba(0, 0, 0, 0.65);user-select:none;will-change: left;z-index: 9;background: #fafafa url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA3hpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDIxIDc5LjE1NTc3MiwgMjAxNC8wMS8xMy0xOTo0NDowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo0ZDhlNWY5My05NmI0LTRlNWQtOGFjYi03ZTY4OGYyMTU2ZTYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTEyNTVEMURGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTEyNTVEMUNGMkVFMTFFNEI5NDBCMjQ2M0ExMDQ1OUYiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTQgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo2MTc5NzNmZS02OTQxLTQyOTYtYTIwNi02NDI2YTNkOWU5YmUiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NGQ4ZTVmOTMtOTZiNC00ZTVkLThhY2ItN2U2ODhmMjE1NmU2Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+YiRG4AAAALFJREFUeNpi/P//PwMlgImBQkA9A+bOnfsIiBOxKcInh+yCaCDuByoswaIOpxwjciACFegBqZ1AvBSIS5OTk/8TkmNEjwWgQiUgtQuIjwAxUF3yX3xyGIEIFLwHpKyAWB+I1xGSwxULIGf9A7mQkBwTlhBXAFLHgPgqEAcTkmNCU6AL9d8WII4HOvk3ITkWJAXWUMlOoGQHmsE45ViQ2KuBuASoYC4Wf+OUYxz6mQkgwAAN9mIrUReCXgAAAABJRU5ErkJggg==) center no-repeat;&:hover {cursor: move;}}.title {position: absolute;left: 50%;transform: translateX(-50%);background-color: transparent;z-index: 2;}.success {position: absolute;height: 100%;background-color: #1e8e3e;z-index: 1;}}
