HTML+CSS 开发简单组件(二)
仿制网易滑块验证
废话不说,直接上代码
- html部分
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>html+css+js编写滑块验证码</title>
<link rel="stylesheet" type="text/css" href="index.css"/>
</head>
<body>
<div class="box" id="box" data-isTrue="false">
<!-- 包围盒,图片位置 -->
<div class="slider" id="slider">
<!-- 滑块条 -->
<span></span>
<!-- 滑块按钮 -->
</div>
</div>
</body>
<script src="index.js" type="text/javascript" charset="utf-8"></script>
</html>
- css部分
* {
margin: 0;
padding: 0;
box-sizing: border-box;
/* 设置全部样式,内外边距清空,盒子模型 */
outline: none;
/* 设置轮廓为空 */
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* 兼容定义用户不可选择 */
}
body {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
/* 网页高度满屏高,设置flex布局,为了方便看 */
}
.box {
/* width: 400px; */
/* height: 270px; */
/* 定义包围盒的尺寸 */
--width: 400px;
/* 宽度 */
--height: 270px;
/* 高度 */
--pacher-width: 56px;
/* 阴影部分宽度 */
--pacher-height: 56px;
/* 阴影部分高度 */
--movely: 0px;
/* 平移位置 */
/* 定义css变量 */
width: var(--width);
height: var(--height);
/* 使用变量来设置宽度高度 */
border-radius: 4px;
/* 加入一个圆角 */
background-image: url(img.jpg);
/* 给包围盒设定一个背景图片 */
position: relative;
/* 设置相对定位 */
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
/* 设定一个阴影,让其变得略微美观 */
}
.box::before,
.box::after {
position: absolute;
/* 设定绝对定位 */
display: block;
/* 设定为块级元素 */
content: '';
/* 想要将元素显示出来,必须填写content */
width: inherit;
height: inherit;
/* 宽度高度与父级元素保持一致 */
background-image: inherit;
background-size: inherit;
background-position: inherit;
/* 背景图片,背景尺寸,背景定位与父级元素保持一致 */
clip-path: inset(
calc( (var(--height) - var(--pacher-height)) / 2 )
var(--pacher-width)
calc( (var(--height) - var(--pacher-height)) / 2 )
calc( var(--width) - var(--pacher-width) * 2 )
);
/* 设定一个剪裁路径 */
-webkit-clip-path: inset(
calc( (var(--height) - var(--pacher-height)) / 2 )
var(--pacher-width)
calc( (var(--height) - var(--pacher-height)) / 2 )
calc( var(--width) - var(--pacher-width) * 2 )
);
/* 设定兼容的剪裁路径 */
}
.box::after{
transform: translateX(
clamp(
calc( var(--width) * -1 ),
calc( (var(--width) * -1) + var(--movely) ),
calc( var(--pacher-width) )
)
);
/* 设定一个平移,让滑块位移出包围盒 */
/* 并且让滑块的位置与图像位置垂直对齐 */
}
.box::before{
background-color: rgba(0,0,0,.35);
/* 设定内部模块背景颜色 */
background-blend-mode: multiply;
/* 设定渲染模式 */
}
.slider{
width: calc( var(--width) + var(--pacher-width) * 2 );
height: 30px;
/* 设定滑块条尺寸 */
border-radius: 15px;
/* 设置滑块条圆角 */
background-color: #eeeeee;
/* 设定滑块条背景颜色 */
position: absolute;
/* 设定绝对定位 */
bottom: -48px;
/* 让滑块条出现在包围盒下方 */
left: calc( var(--pacher-width) * -2);
/* 设定滑块条右侧与包围盒右侧对齐 */
box-shadow: inset 0 0 12px rgba(0,0,0,.2);
/* 为滑块条添加一个向内的阴影 */
border: 3px solid #b9bdc8;
/* 为滑块条添加一个边框线 */
}
.slider>span{
display: block;
/* 设定滑块按钮为块级元素 */
width: var(--pacher-width);
height: 100%;
/* 设置滑块按钮的尺寸 */
border-radius: inherit;
/* 圆角与父级元素持平 */
background-color: #FFFFFF;
/* 设置背景颜色 */
box-shadow: inset 0 0 6px rgba(0,0,0,.25),0 2px 4px rgba(0,0,0,.3);
/* 设置向内的阴影 */
position: absolute;
/* 设定绝对定位 */
cursor: pointer;
/* 为滑块按钮添加一个鼠标指针为手型 */
transform: translateX(
clamp(
0px,
var(--movely),
calc( var(--width) + var(--pacher-width) )
)
);
/* 设定滑块按钮平移位置 */
}
.box.ok::before,
.box.ok::after,
.box.ok>.slider{
opacity: 0;
transition-duration: .4s;
}
/* 如果包围盒上产生了".ok"选择器,说明已经成功验证,那么将多余部分隐去 */
- js部分
const box = document.querySelector("#box");
// 获取包围盒
const slider = document.querySelector("#slider");
// 获取滑块条
const button = document.querySelector("#slider>span");
// 获取滑块按钮
let flag = false;
// 设定一个开关,用来判断鼠标是否处于按下的状态
button.addEventListener("mousedown",e=>{
flag = true;
});
// 绑定鼠标按下事件
window.addEventListener("mousemove",e=>{
// 使用window的目的是让鼠标在移出滑块条时,事件依旧生效
if(flag){
const offLeft = slider.getBoundingClientRect().left;
const btnWidth = button.getBoundingClientRect().width;
// 计算偏移尺寸
box.style.setProperty('--movely',`${e.clientX - offLeft - btnWidth / 2}px`)
// 为包围盒的css变量更换值,切记要加px,不然会大问题
}
});
// 绑定鼠标移动事件
window.addEventListener("mouseup",e=>{
// 使用window的目的是让鼠标在移出滑块条时,事件依旧生效
if(flag){
const lastOffset = e.clientX - slider.getBoundingClientRect().left;
// 计算偏移
if(lastOffset>=418&&lastOffset<=438){
box.dataset.isTrue = "true";
// 如果拖拽成功,先给定一个dataset值为真,确保工作人员可以直接获取到结果
box.classList.add("ok");
// 然后给包围盒一个".ok"的选择器,以便于css进行控制
}else{
box.style.setProperty('--movely','0px');
// 如果未验证成功,将回滚到初始位置
}
flag = false;
}
});
// 绑定鼠标抬起事件