目录
1. window效果
这里是window11的效果
2. 实现思路
1. 元素分析
1. 只要包含在拉选框内的都会被选中,这样就需要获取拉选框的x,y,height,width和元素的x,y,widht,height来进行组合判断。
2. 获取元素的所需要的属性可以使用getBoundingClientRect方法来获取这个矩形的属性值
3. 图标元素的x,y就等于getBoundingClientRect().x ,getBoundingClientRect().x。widht和height相同的原理
2. 思路分析
1. 拉选框是一个绝对定位的元素,我这里使用div
// css
.box{
position: absolute;
background-color: rgba(13, 153, 255, 0.3);
border: 1px solid rgb(13, 153, 255);
}
// js
const box = document.createElement('div');
box.className = 'box';
2. 给拉选框添加事件
1.mousedown 向body添加box元素并添加move,up事件
function mouseDown(e){
box.style.width = '0px';
box.style.height = '0px';
body.append(box);
// initPosition 记录初始坐标
initPosition.x = e.clientX;
initPosition.y = e.clientY;
box.style.top = e.clientY + 'px';
box.style.left = e.clientX + 'px';
body.addEventListener('mousemove', mouseMove);
body.addEventListener('mouseup', mouseUp);
}
2.mousemove 初始坐标为定点想象一个象限轴,可以有四个方向移动
function mouseMove(e){
const {x,y} = initPosition;
// 设置移动位置
const moveX = e.clientX;
const moveY = e.clientY;
// 计算移动后对应元素宽高
const width = Math.abs(x - moveX);
const height = Math.abs(y - moveY);
// 判断方向及顶点位置
if(moveX > x && moveY > y){ // 4象限
box.style.left = x + 'px';
box.style.top = y + 'px';
}else if(y > moveY && x < moveX){ // 1象限
box.style.top = moveY + 'px';
box.style.left = x + 'px';
}else if(moveX < x && moveY > y){ // 3象限
box.style.left = moveX + 'px';
box.style.top = y + 'px';
}else if(moveY < y && moveX < x){ // 2象限
box.style.top = moveY + 'px';
box.style.left = moveX + 'px';
}
requestAnimationFrame(() => {
box.style.width = width + 'px';
box.style.height = height + 'px';
})
}
3.mouseup 鼠标抬起时应该移除box元素和move,up事件
function mouseUp(){
body.removeChild(box);
body.removeEventListener('mousemove', mouseMove);
body.removeEventListener('mouseup', mouseUp);
}
3. 实现拉选框
1. 代码
const body = document.querySelector('body');
const box = document.createElement('div');
box.className = 'box';
body.addEventListener('mousedown', mouseDown);
function mouseDown(e){
box.style.width = '0px';
box.style.height = '0px';
selectArr = [];
body.append(box);
initPosition.x = e.clientX;
initPosition.y = e.clientY;
box.style.top = e.clientY + 'px';
box.style.left = e.clientX + 'px';
body.addEventListener('mousemove', mouseMove);
body.addEventListener('mouseup', mouseUp);
}
function mouseMove(e){
const {x,y} = initPosition;
// 设置移动位置
const moveX = e.clientX;
const moveY = e.clientY;
// 计算移动后对应元素宽高
const width = Math.abs(x - moveX);
const height = Math.abs(y - moveY);
// 判断方向及顶点位置
if(moveX > x && moveY > y){ // 4
box.style.left = x + 'px';
box.style.top = y + 'px';
}else if(y > moveY && x < moveX){ // 1
box.style.top = moveY + 'px';
box.style.left = x + 'px';
}else if(moveX < x && moveY > y){ // 3
box.style.left = moveX + 'px';
box.style.top = y + 'px';
}else if(moveY < y && moveX < x){ // 2
box.style.top = moveY + 'px';
box.style.left = moveX + 'px';
}
requestAnimationFrame(() => {
box.style.width = width + 'px';
box.style.height = height + 'px';
// isSelect();
})
}
function mouseUp(){
body.removeChild(box);
body.removeEventListener('mousemove', mouseMove);
body.removeEventListener('mouseup', mouseUp);
}
2. 实现效果
4. 实现元素选中效果
1. 获取所有元素的我们需要的属性
function initSelectBox(){
const domArr = document.querySelectorAll('.select');
for(let i = 0; i < domArr.length; i++){
const item = domArr[i];
const obj = {
dom:item,
x:item.getBoundingClientRect().left,
y:item.getBoundingClientRect().top,
width:item.getBoundingClientRect().width,
height:item.getBoundingClientRect().height,
}
select.push(obj);
}
}
2. 判断是否选中了某个元素并改变他的颜色
function isSelect(){
const {width, height, left, top} = box.getBoundingClientRect();
for(let i = 0; i < select.length; i++){
const item = select[i];
if(
left < item.x + item.width &&
item.x < left + width &&
top < item.y + item.height &&
item.y < top + height
){
if(!selectArr.find(items => items === item)){ // 如果selectArr里有item元素则不push
selectArr.push(item);
}
item.dom.style.backgroundColor = 'rgba(13, 153, 255, 0.3)';
}else{
if(selectArr.find(items => items === item)){ // 如果能找到item元素则从selectArr里删除该元素
selectArr.splice(selectArr.findIndex(items => items === item), 1);
}
item.dom.style.backgroundColor = 'rgba(122, 145, 161)';
}
}
}
3. 实现效果
5. 完整代码
<!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>
*{
margin: 0;
padding: 0;
}
body{
width: 100vw;
height: 100vh;
position: relative;
}
.box{
position: absolute;
background-color: rgba(13, 153, 255, 0.3);
border: 1px solid rgb(13, 153, 255);
}
.container{
width: 100vw;
height: 100vh;
}
.item{
display: flex;
}
.select{
cursor: pointer;
margin: 100px;
width: 100px;
height: 100px;
min-width: 100px;
min-height: 100px;
background-color: rgba(122, 145, 161, 1);
}
</style>
</head>
<body>
<div class="container">
<div class="item">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
</div>
<div class="item">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
</div>
</div>
<script>
const body = document.querySelector('body');
const box = document.createElement('div');
box.className = 'box';
const select = [];
let selectArr = []
const initPosition = {
x: 0,
y: 0
}
initSelectBox();
function initSelectBox(){
const domArr = document.querySelectorAll('.select');
for(let i = 0; i < domArr.length; i++){
const item = domArr[i];
const obj = {
dom:item,
x:item.getBoundingClientRect().left,
y:item.getBoundingClientRect().top,
width:item.getBoundingClientRect().width,
height:item.getBoundingClientRect().height,
}
select.push(obj);
}
}
body.addEventListener('mousedown', mouseDown);
function mouseDown(e){
box.style.width = '0px';
box.style.height = '0px';
selectArr = [];
body.append(box);
initPosition.x = e.clientX;
initPosition.y = e.clientY;
box.style.top = e.clientY + 'px';
box.style.left = e.clientX + 'px';
body.addEventListener('mousemove', mouseMove);
body.addEventListener('mouseup', mouseUp);
}
function mouseMove(e){
const {x,y} = initPosition;
// 设置移动位置
const moveX = e.clientX;
const moveY = e.clientY;
// 计算移动后对应元素宽高
const width = Math.abs(x - moveX);
const height = Math.abs(y - moveY);
// 判断方向及顶点位置
if(moveX > x && moveY > y){ // 4
box.style.left = x + 'px';
box.style.top = y + 'px';
}else if(y > moveY && x < moveX){ // 1
box.style.top = moveY + 'px';
box.style.left = x + 'px';
}else if(moveX < x && moveY > y){ // 3
box.style.left = moveX + 'px';
box.style.top = y + 'px';
}else if(moveY < y && moveX < x){ // 2
box.style.top = moveY + 'px';
box.style.left = moveX + 'px';
}
requestAnimationFrame(() => {
box.style.width = width + 'px';
box.style.height = height + 'px';
isSelect();
})
}
function mouseUp(){
console.log(selectArr)
body.removeChild(box);
body.removeEventListener('mousemove', mouseMove);
body.removeEventListener('mouseup', mouseUp);
}
// 判断box是否选中元素
function isSelect(){
const {width, height, left, top} = box.getBoundingClientRect();
for(let i = 0; i < select.length; i++){
const item = select[i];
if(
left < item.x + item.width &&
item.x < left + width &&
top < item.y + item.height &&
item.y < top + height
){
if(!selectArr.find(items => items === item)){
selectArr.push(item);
}
item.dom.style.backgroundColor = 'rgba(13, 153, 255, 0.3)';
}else{
if(selectArr.find(items => items === item)){
selectArr.splice(selectArr.findIndex(items => items === item), 1);
}
item.dom.style.backgroundColor = 'rgba(122, 145, 161)';
}
}
}
</script>
</body>
</html>
6. 总结
大概的实现思路就是这样,网络上也会有更优的方法,我写的还一点小bug如果大家发现并能修复可以告诉博主,感谢!!!