标签:滑块 captcha 拼图 px H5 -- let height width
展示效果
逻辑概述
使用背景图片的继承父节点样式的三张图片,子节点通过使用clip-path裁切图片,通过位置偏移来达成移动效果。
主要代码
布局
<div id="captcha">
<div id="handle">
<span></span>
</div>
</div>
样式
#captcha {
display: block;
width: var(--width);
height: var(--height);
border-radius: 4px;
background-image: url(https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2676921178,3792372773&fm=55&app=54&f=JPEG?w=1680&h=630);
background-size: cover;
background-position: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
position: relative;
box-sizing: border-box;
}
#captcha::before,
#captcha::after {
position: absolute;
content: "";
display: block;
width: inherit;
height: inherit;
background-image: inherit;
background-size: inherit;
background-position: inherit;
clip-path: var(--clip-path);
--webkit-clip-path: var(--clip-path);
}
#captcha::after {
transform: translateX(calc(var(--clip-offsetX) * -1 + var(--moved)));
transition: .25s all ease-in-out;
}
#captcha::before {
background-color: rgba(0, 0, 0, .5);
background-blend-mode: multiply;
}
#captcha:active #handle span,
#captcha:active::after {
transition: none;
}
#captcha #handle {
width: calc(var(--width) - (3px * 2));
height: 30px;
border-radius: 18px;
background-color: #eee;
position: absolute;
bottom: -50px;
left: 0;
box-shadow: inset 0 0 12px rgba(0, 0, 0, .2);
border: 3px solid #ccc;
}
#handle span {
display: block;
width: var(--puzzle-width);
height: inherit;
border-radius: inherit;
background-color: #fff;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .25), 0 2px 4px rgba(0, 0, 0, .3);
position: absolute;
cursor: move;
transform: translateX(var(--moved));
transition: .25s all ease-in-out;
}
#captcha.passed #handle,
#captcha.passed::after,
#captcha.passed::before {
opacity: 0;
}
控制
let width = 400; // 宽度
let height = 260; // 高度
let puzzleWidth = 80; // 切图宽
let puzzleHeight = 80; // 切图高
let moved = 0; // 移动位置
let mpe = 5; // 允许最大误差
let offsetX = 6; // 边距值
let offsetY = 0; // 边距值
let shouldMove = false;
let clipRectX1 = randomRange(puzzleWidth + offsetX, width - puzzleWidth - offsetX);
let clipRectX2 = clipRectX1 + puzzleWidth;
let clipRectY1 = randomRange(puzzleHeight + offsetX, height - puzzleHeight - offsetY);
let clipRectY2 = clipRectY1 + puzzleHeight;
let captcha = document.querySelector('#captcha');
let handle = document.querySelector('#handle');
let button = document.querySelector('#handle span');
button.addEventListener("mousedown", (e) => {
shouldMove = true;
})
window.addEventListener("mousemove", (e) => {
if (shouldMove) {
const offsetLeft = handle.getBoundingClientRect().left;
const buttonWidth = button.getBoundingClientRect().width;
moved = e.clientX - offsetLeft - buttonWidth / 2;
render();
}
})
window.addEventListener("mouseup", (e) => {
if (shouldMove) {
const finalOffset = e.clientX - handle.getBoundingClientRect().left - puzzleWidth / 2;
if (Math.abs(finalOffset - clipRectX1) < mpe) captcha.classList.add('passed')
else moved = 0;
render();
shouldMove = false;
}
})
/**
* 超出省略
*/
function clamp(num, a, b) {
return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b))
}
/**
* 随机数字
*/
function randomRange(min, max) {
return Math.round(Math.random() * (max - min)) + min
}
/**
* 渲染
*/
function render() {
let clipPath = `polygon( ${clipRectX1}px ${clipRectY1}px, ${clipRectX2}px ${clipRectY1}px, ${clipRectX2}px ${clipRectY2}px, ${clipRectX1}px ${clipRectY2}px )`;
captcha.style = `--clip-offsetX:${clipRectX1}px;--moved:${clamp(moved, 0, width - puzzleWidth - offsetX)}px;--clip-path:${clipPath};--width:${width}px;--height:${height}px;--puzzle-width:${puzzleWidth}px;--puzzle-height:${puzzleHeight}px`;
}
render();
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
#captcha {
display: block;
width: var(--width);
height: var(--height);
border-radius: 4px;
background-image: url(https://dss1.baidu.com/6ONXsjip0QIZ8tyhnq/it/u=2676921178,3792372773&fm=55&app=54&f=JPEG?w=1680&h=630);
background-size: cover;
background-position: center;
box-shadow: 0 2px 4px rgba(0, 0, 0, .3);
position: relative;
box-sizing: border-box;
}
#captcha::before,
#captcha::after {
position: absolute;
content: "";
display: block;
width: inherit;
height: inherit;
background-image: inherit;
background-size: inherit;
background-position: inherit;
clip-path: var(--clip-path);
--webkit-clip-path: var(--clip-path);
}
#captcha::after {
transform: translateX(calc(var(--clip-offsetX) * -1 + var(--moved)));
transition: .25s all ease-in-out;
}
#captcha::before {
background-color: rgba(0, 0, 0, .5);
background-blend-mode: multiply;
}
#captcha:active #handle span,
#captcha:active::after {
transition: none;
}
#captcha #handle {
width: calc(var(--width) - (3px * 2));
height: 30px;
border-radius: 18px;
background-color: #eee;
position: absolute;
bottom: -50px;
left: 0;
box-shadow: inset 0 0 12px rgba(0, 0, 0, .2);
border: 3px solid #ccc;
}
#handle span {
display: block;
width: var(--puzzle-width);
height: inherit;
border-radius: inherit;
background-color: #fff;
box-shadow: inset 0 0 6px rgba(0, 0, 0, .25), 0 2px 4px rgba(0, 0, 0, .3);
position: absolute;
cursor: move;
transform: translateX(var(--moved));
transition: .25s all ease-in-out;
}
#captcha.passed #handle,
#captcha.passed::after,
#captcha.passed::before {
opacity: 0;
}
</style>
</head>
<body>
<div id="captcha">
<div id="handle">
<span></span>
</div>
</div>
<script>
let width = 400; // 宽度
let height = 260; // 高度
let puzzleWidth = 80; // 切图宽
let puzzleHeight = 80; // 切图高
let moved = 0; // 移动位置
let mpe = 5; // 允许最大误差
let offsetX = 6; // 边距值
let offsetY = 0; // 边距值
let shouldMove = false;
let clipRectX1 = randomRange(puzzleWidth + offsetX, width - puzzleWidth - offsetX);
let clipRectX2 = clipRectX1 + puzzleWidth;
let clipRectY1 = randomRange(puzzleHeight + offsetX, height - puzzleHeight - offsetY);
let clipRectY2 = clipRectY1 + puzzleHeight;
let captcha = document.querySelector('#captcha');
let handle = document.querySelector('#handle');
let button = document.querySelector('#handle span');
button.addEventListener("mousedown", (e) => {
shouldMove = true;
})
window.addEventListener("mousemove", (e) => {
if (shouldMove) {
const offsetLeft = handle.getBoundingClientRect().left;
const buttonWidth = button.getBoundingClientRect().width;
moved = e.clientX - offsetLeft - buttonWidth / 2;
render();
}
})
window.addEventListener("mouseup", (e) => {
if (shouldMove) {
const finalOffset = e.clientX - handle.getBoundingClientRect().left - puzzleWidth / 2;
if (Math.abs(finalOffset - clipRectX1) < mpe) captcha.classList.add('passed')
else moved = 0;
render();
shouldMove = false;
}
})
/**
* 超出省略
*/
function clamp(num, a, b) {
return Math.max(Math.min(num, Math.max(a, b)), Math.min(a, b))
}
/**
* 随机数字
*/
function randomRange(min, max) {
return Math.round(Math.random() * (max - min)) + min
}
/**
* 渲染
*/
function render() {
let clipPath = `polygon( ${clipRectX1}px ${clipRectY1}px, ${clipRectX2}px ${clipRectY1}px, ${clipRectX2}px ${clipRectY2}px, ${clipRectX1}px ${clipRectY2}px )`;
captcha.style = `--clip-offsetX:${clipRectX1}px;--moved:${clamp(moved, 0, width - puzzleWidth - offsetX)}px;--clip-path:${clipPath};--width:${width}px;--height:${height}px;--puzzle-width:${puzzleWidth}px;--puzzle-height:${puzzleHeight}px`;
}
render();
</script>
</body>
</html>
标签:滑块,captcha,拼图,px,H5,--,let,height,width 来源: https://www.cnblogs.com/linyisonger/p/14943308.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。