最近看不少B站UP主在视频开始or结束都会请求观众来个一键三连,具体操作就是用户长按点赞按钮,一段时间后会触发某个事件,一次性完成点赞、投币和收藏操作。下面将从前端工程师的角度,来分析一下这个过程,并给出我的实现方式~
首先来说,实现一键三连需要同时满足两个必要条件,一是「点击」点赞按钮,二是需要长按。上面的「点击」我用引号进行了标记,是因为用户感知的「点击」行为是比较抽象的,而在前端工程师眼里触发click
事件会经历一个有序触发相关事件的过程。
首先在PC端,前端工程师眼里触发click
事件会先依次触发mousedown
和mouseup
事件。而在移动端,触发click
事件会先依次触发touchstart
和touchend
事件。
根据click
事件规范,我们知道在PC端鼠标按下任意键并释放该键之后会触发click
,「按下」和「释放」对应mousedown
和mouseup
事件。移动端因为页面滚动等操作需要手指触摸屏幕来完成,因此触发click
事件之前,会先依次触发touchstart
和touchend
事件。基于上述理解可知mouseup/touchend
事件和click
事件之间的时间间隔很小,要实现「长按」操作,最优选择是在mousedown/touchstart
和mouseup/touchend
事件之间执行相关操作。下面将实现一种一键三连的效果
需求
长按3秒点赞,一键三连;长按时间少于1s则视为仅点赞;长按时间在1s至3s之间,视为一键三连失败,不做任何操作。
实现方案
-
在
mousedown/touchstart
事件触发时,记录触发时间,同时通过setTimeout
设置定时器 -
在
mouseup/touchend
事件触发时,计算当前时间和mousedown/touchstart
事件触发时的时间差,根据时间差决定进一步操作。
具体实现如下:
//html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="viewport" content="user-scalable=no">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
#clickBtn {
width: 60px;
height: 40px;
background: red;
}
</style>
</head>
<body>
<div id="clickBtn"></div>
<p id="timeText"></p>
</body>
</html>
//点赞、一键三连方法
function like(){
console.log("点赞");
}
function longPress(){
console.log("一键三连");
}
function getTime() {
const now = new Date().getTime();
timeText.innerText = (now - start) / 1000;
}
PC端实现方式:
let timer, startTime, setTimeText;
let start = new Date().getTime();
const clickBtn = document.getElementById("clickBtn");
const timeText = document.getElementById("timeText");
timeText.innerText = "";
clickBtn.addEventListener("mousedown",function(){
startTime = new Date().getTime();//获取mousedown触发时间
setTimeText = setInterval(getTime, 100);
timer = setTimeout(longPress, 3000);//设置定时器
});
clickBtn.addEventListener("mouseup",function(){
const now = new Date().getTime(); //获取mouseup触发时间
clearInterval(setTimeText);
if (now - startTime < 1000) { //点按仅触发点赞
like();
clearTimeout(timer);
} else if (now - startTime < 3000) { //长按时间不足,不触发任何操作
clearTimeout(timer);
}
});
移动端实现只需要将对应事件替换为touchstart
和touchend
即可~