前端开发中的防误触按钮的形式:滑动触发事件 长摁触发事件
滑动触发事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
body {
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
gap: 50px;
}
.track {
position: relative;
width: 500px;
height: 50px;
line-height: 50px;
text-align: center;
background-color: #ccc;
border-radius: 5px;
overflow: hidden;
font-size: 32px;
}
.progress {
position: absolute;
top: 0;
left: 0;
height: 100%;
background-color: skyblue;
}
.slider {
position: absolute;
top: 0;
left: 0;
width: 50px;
height: 50px;
background-color: lemonchiffon;
cursor: pointer;
}
.act-info {
position: absolute;
}
</style>
</head>
<body>
<div class="track">
<div class="progress"></div>
<div class="slider"></div>
<span class="act-info">拖动触发事件</span>
</div>
<script>
const track = document.querySelector(".track");
const slider = document.querySelector(".slider");
const progress = document.querySelector(".progress");
let isDragging = false;
let startX, startLeft;
let isComplete = false;
// 记录初始位置
const initialPosition = 0;
// 触摸事件处理
slider.addEventListener("touchstart", startDrag, { passive: false });
document.addEventListener("touchmove", handleDrag, { passive: false });
document.addEventListener("touchend", endDrag);
// 鼠标事件处理
slider.addEventListener("mousedown", startDrag);
document.addEventListener("mousemove", handleDrag);
document.addEventListener("mouseup", endDrag);
function startDrag(e) {
console.log("drag start");
isDragging = true;
slider.style.transition = "none";
// 获取初始位置,兼容鼠标和触摸事件
const clientX = e.type.includes("mouse")
? e.clientX
: e.touches[0].clientX;
startX = clientX;
startLeft = slider.getBoundingClientRect().left;
isComplete = false;
// 阻止默认行为,防止页面滚动
if (e.type.includes("touch")) {
e.preventDefault();
}
}
function handleDrag(e) {
if (!isDragging) return;
console.log("dragging");
// 阻止默认行为,防止页面滚动
if (e.type.includes("touch")) {
e.preventDefault();
}
const wrapperRect = track.getBoundingClientRect();
// 获取当前位置,兼容鼠标和触摸事件
const clientX = e.type.includes("mouse")
? e.clientX
: e.touches[0].clientX;
const newX = Math.min(
Math.max(clientX - startX + startLeft - wrapperRect.left, 0),
wrapperRect.width - slider.offsetWidth
);
slider.style.left = `${newX}px`;
progress.style.width = `${(newX / wrapperRect.width) * 100}%`;
// 检查是否到达最右侧
if (newX === wrapperRect.width - slider.offsetWidth) {
isComplete = true;
alert("Done");
} else {
isComplete = false;
}
}
function endDrag() {
console.log("drag end");
if (!isDragging) return;
isDragging = false;
slider.style.transition = "left 0.2s ease";
// 如果没有完成,重置位置
if (!isComplete) {
slider.style.left = `${initialPosition}px`;
progress.style.width = "0%";
}
}
</script>
</body>
</html>
长摁触发事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>逐渐拼凑的长方形进度条</title>
<style>
@import url("https://fonts.googleapis.com/css?family=Lato:700");
* {
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #ecf0f1;
font-family: "Lato", sans-serif;
}
.progress-btn-wrapper {
width: 300px;
height: 150px;
position: relative;
}
.progress {
width: 100%;
height: 100%;
border-radius: 5px;
position: absolute;
background: conic-gradient(
#3498db 0deg,
#3498db 0deg,
transparent 0deg
);
transition: background 0.5s linear; /* Smooth transition */
}
.btn {
position: absolute;
width: 270px;
height: 120px;
border-radius: 5px;
background: #34495e;
top: 15px;
left: 15px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 2em;
}
.progress-text {
font-size: 1.5em;
}
</style>
</head>
<body>
<div class="progress-btn-wrapper">
<div class="progress"></div>
<div class="btn">
<span class="progress-text">0%</span>
</div>
</div>
<script>
const progressText = document.querySelector(".progress-text");
const progress = document.querySelector(".progress");
const btn = document.querySelector(".btn");
const duration = 2000;
const step = 5;
const interval = duration / (100 / step);
let progressTimer = null;
let percent = 0;
// 按下时开始进度条
btn.addEventListener("touchstart", (e) => {
e.preventDefault();
if (progressTimer) return; // 防止重复启动
timer = setTimeout(() => {
complete();
}, duration);
progressTimer = setInterval(() => {
percent += step;
if (percent > 100) percent = 100;
updateProgress(percent);
}, interval);
});
// 松开时平滑回退进度条
btn.addEventListener("touchend", () => {
clearInterval(progressTimer);
progressTimer = null;
// 如果进度条不是 100%,平滑回退
if (percent < 100) {
smoothRevert();
}
});
// 更新进度条和进度文本
function updateProgress(percent) {
const degrees = (percent / 100) * 360;
progress.style.background = `conic-gradient(#3498db 0deg, #3498db ${degrees}deg, transparent ${degrees}deg)`;
progressText.textContent = `${percent}%`;
}
// 平滑回退进度条
function smoothRevert() {
const revertInterval = 10; // 回退动画间隔
const revertStep = 1; // 回退步长
clearTimeout(timer);
const revertTimer = setInterval(() => {
percent -= revertStep;
if (percent <= 0) {
clearInterval(revertTimer);
percent = 0;
updateProgress(percent);
} else {
updateProgress(percent);
}
}, revertInterval);
}
// 完成后的处理逻辑
function complete() {
console.log("开始执行业务逻辑");
}
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Touch Progress Example</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
#container {
width: 200px;
height: 88px;
border: 1px solid black;
position: relative;
}
#progress {
width: 0%;
height: 100%;
background-color: skyblue;
transition: width 1s linear;
position: absolute;
z-index: 2;
}
#text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 3;
}
</style>
</head>
<body>
<div id="container">
<div id="text">Long Press</div>
<div id="progress"></div>
</div>
<script>
// 获取元素
const container = document.getElementById("container");
const pickupProgress = document.getElementById("progress");
const text = document.getElementById("text");
let touchEventTimer = null;
//这个事件负责
const handleTouchStart = (e) => {
e.preventDefault();
pickupProgress.style.width = "100%";
touchEventTimer = setTimeout(() => {
console.log("开始执行touch完成后的事件逻辑");
touchEventTimer = null;
}, 1000);
console.log("touch开始", touchEventTimer);
};
const handleTouchEnd = () => {
console.log("touch结束");
//未touch 1s 终止计时的任务
if (touchEventTimer) {
pickupProgress.style.width = "0%";
clearTimeout(touchEventTimer);
touchEventTimer = null;
} else {
text.innerText = "Finished";
pickupProgress.style.background = "pink";
}
};
if (container) {
container.addEventListener("touchstart", handleTouchStart, {
passive: false,
});
container.addEventListener("touchend", handleTouchEnd, {
passive: false,
});
}
</script>
</body>
</html>