今天我们来聊一下怎么使用原生javascript编写一个简单的框选功能。
需求描述
鼠标左键按下不放,移动鼠标出现矩形选框;
鼠标左键松开,根据上边出现的矩形选框统计选框范围内的DOM元素;
嗯...上边的功能描述看着是挺简单的,但实现起来也还是会有些地方需要斟酌思考的。比如,如果我们的框选范围不是document.body,而是某一个div里边进行框选呢?而现实开发过程中,我们会遇上的应该就是第二种情况。
怎么实现
二话不说,咱们动手写代码吧!因为更好的兼容性,这里就避免了一些ES6的语法,如果是用的其他框架来写的话,代码上相应的也要做一些调整。
.fileDiv {
display: inline-block;
width: 100px;
height: 100px;
margin: 24px;
background-color: blue;
}
添加鼠标事件监听
由于js自身并没有带有鼠标点击按住不放这样子的事件,这里我们不仅需要检测鼠标左键点击按下,还要加一个定时器来检测鼠标是否按住不放了。
(function () {
// 定时器id
var mouseStopId;
// 是否开启框选功能
var mouseOn = false;
// 用来存放鼠标点击初始位置
var startX = 0;
var startY = 0;
// 添加鼠标按下监听事件
document.body.addEventListener('mousedown', function (e) {
// 阻止事件冒泡
clearEventBubble(e);
// 判断是否为鼠标左键被按下
if (e.buttons !== 1 || e.which !== 1) return;
mouseStopId = setTimeout(function () {
mouseOn = true;
startX = e.clientX;
startY = e.clientY;
}, 300); // 间隔300毫秒后执行,判定这时候鼠标左键被按住不放
});
// 添加鼠标移动事件监听
document.body.addEventListener('mousemove', function (e) {
// 如果并非框选开启,退出
if (!mouseOn) return;
// 阻止事件冒泡
clearEventBubble(e);
// 处理鼠标移动
// codes
});
// 添加鼠标点击松开事件监听
document.body.addEventListener('mouseup', function (e) {
// 阻止事件冒泡
clearEventBubble(e);
// 处理鼠标点击松开
// codes
});
function clearEventBubble (e) {
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
if (e.preventDefault) e.preventDefault();
else e.returnValue = false;
}
})();
添加框选可视化元素
框选可视化元素示意图
我们有了事件监听还不够,为了更好的交互效果,我们需要一个随时跟随着鼠标移动的框选框元素,用于让用户随时感知框选范围。
(function () {
var mouseStopId;
var mouseOn = false;
var startX = 0;
var startY = 0;
document.body.addEventListener('mousedown', function (e) {
clearEventBubble(e);
if (e.buttons !== 1 || e.which !== 1) return;
mouseStopId = setTimeout(fu