使用原生js编写一个简单的框选功能方法

今天我们来聊一下怎么使用原生javascript编写一个简单的框选功能。

需求描述

鼠标左键按下不放,移动鼠标出现矩形选框;

鼠标左键松开,根据上边出现的矩形选框统计选框范围内的DOM元素;

嗯...上边的功能描述看着是挺简单的,但实现起来也还是会有些地方需要斟酌思考的。比如,如果我们的框选范围不是document.body,而是某一个div里边进行框选呢?而现实开发过程中,我们会遇上的应该就是第二种情况。

点击查看完整的源码

怎么实现

二话不说,咱们动手写代码吧!因为更好的兼容性,这里就避免了一些ES6的语法,如果是用的其他框架来写的话,代码上相应的也要做一些调整。

<head> <style> .fileDiv { display: inline-block; width: 100px; height: 100px; margin: 24px; background-color: blue; } </style> </head> <body> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> <div></div> </body>

添加鼠标事件监听

由于js自身并没有带有鼠标点击按住不放这样子的事件,这里我们不仅需要检测鼠标左键点击按下,还要加一个定时器来检测鼠标是否按住不放了。

<script> (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; } })(); </script>

添加框选可视化元素

使用原生js编写一个简单的框选功能方法

框选可视化元素示意图

我们有了事件监听还不够,为了更好的交互效果,我们需要一个随时跟随着鼠标移动的框选框元素,用于让用户随时感知框选范围。

<script> (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(function () { mouseOn = true; startX = e.clientX; startY = e.clientY; // 创建一个框选元素 var selDiv = document.createElement('div'); // 给框选元素添加css样式,这里使用绝对定位 selDiv.style.cssText = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;'; // 添加id selDiv.id = 'selectDiv'; document.body.appendChild(selDiv); // 根据起始位置,添加定位 selDiv.style.left = startX + 'px'; selDiv.style.top = startY + 'px'; }, 300); }); document.body.addEventListener('mousemove', function (e) { if (!mouseOn) return; clearEventBubble(e); // 获取当前坐标 var _x = e.clientX; var _y = e.clientY; // 根据坐标给选框修改样式 var selDiv = document.getElementById('selectDiv'); selDiv.style.display = 'block'; selDiv.style.left = Math.min(_x, startX) + 'px'; selDiv.style.top = Math.min(_y, startY) + 'px'; selDiv.style.width = Math.abs(_x - startX) + 'px'; selDiv.style.height = Math.abs(_y - startY) + 'px'; // 如果需要更直观一点的话,我们还可以在这里进行对框选元素覆盖到的元素进行修改被框选样式的修改。 }); document.body.addEventListener('mouseup', function (e) { clearEventBubble(e); }); function clearEventBubble (e) { if (e.stopPropagation) e.stopPropagation(); else e.cancelBubble = true; if (e.preventDefault) e.preventDefault(); else e.returnValue = false; } })(); </script>

添加鼠标松开事件监听

使用原生js编写一个简单的框选功能方法

元素是否被选中示意图

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/611f82b689232231d1d5363b885ada1b.html