鼠标拖动画框选中并添加到另一个div效果

需求:鼠标按下后,显示div用于放置所有的li;当鼠标框选住li,并抬起鼠标时,所有的li放进div中

思路:

  1. 先移动鼠标生成画框;
  2. 将生成的画框和已有的li进行碰撞,如果碰到了,就设置active,没有就清除active;
  3. 在鼠标放开时,找到所有为active的li,将其appendChild进div中

问题:

  • 不能直接碰撞时,直接appendChild到div中,会将后面的li全部添加进去div
  • 必须给没有碰到的清除active。否则当操作时,先往前拉,后往后拉,会给往前拉的所有li都加上active,这样再往后拉后会全部加到div里
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        #bucket {
            border: 1px solid black;
            height: 240px;
        }
        li {
            display: block;
            width: 100px;
            height: 100px;
            background: yellow;
            border: 1px solid black;
            list-style: none;
            float: left;
            margin: 10px;
        }
        .box {
            border: 1px solid peru;
            position: absolute;
            background: rgba(0,0,255,.4);
        }
        .active {
            background: green;
        }
    </style>
</head>
<body>
<ul id="bucket"></ul>
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
    <li>6</li>
    <li>7</li>
    <li>8</li>
    <li>9</li>
    <li>10</li>
    <li>11</li>
    <li>12</li>
    <li>13</li>
</ul>
<script>
{
    //需求:鼠标按下后,显示div用于放置所有的li;当鼠标框选住li,并抬起鼠标时,所有的li放进div中
    //获取/设置元素的样式
    function css(el,attr,val){
        if(arguments.length == 3){
            el.style[attr] = val+'px';
        }else{
            return parseInt(getComputedStyle(el)[attr]);
        }
    }

    //元素碰撞
    let isConcat = (el1,el2) =>{
        //判断是否碰撞
        let div1Dis = el1.getBoundingClientRect();
        let div2Dis = el2.getBoundingClientRect();
        if(div1Dis.right > div2Dis.left &&
            div1Dis.bottom > div2Dis.top &&
            div1Dis.left < div2Dis.right &&
            div1Dis.top < div2Dis.bottom){
                
                el2.classList.add("active");
                return el2;
        }else{
            //注意:必须给没有碰到的清除active。否则当操作时,先往前拉,后往后拉,会给往前拉的所有li都加上active,这样再往后拉后会全部加到div里
            el2.classList.remove("active");
        }
    }

    document.addEventListener("mousedown",function(e){
        let div = document.createElement("div");
        let startPos = {};
        startPos.x = e.clientX;
        startPos.y = e.clientY;
        let li = null;
        function move(e){
            let curPos = {};
            curPos.x = e.clientX;
            curPos.y = e.clientY;
            
            //移动时画框
            div.classList.add("box");
            //设置div的宽高及top/left
            css(div,"width",Math.abs(curPos.x-startPos.x));
            css(div,"height",Math.abs(curPos.y-startPos.y));
            css(div,"left",Math.min(curPos.x,startPos.x));
            css(div,"top",Math.min(curPos.y,startPos.y));
            
            document.body.appendChild(div);

            let lis = document.querySelectorAll("ul li");
            //将框住的li放进div中(div和多个元素碰撞)
            lis.forEach(item=>{
                // 将每个li和div进行碰撞测试,如果碰到了,就设置active
                //注意:不能直接碰撞时,直接appendChild到div中,会将后面的li全部添加进去
                isConcat(div,item);
            });
        }
        //获取鼠标移动时位置
        document.addEventListener("mousemove",move);
        document.addEventListener("mouseup",function(){
            document.removeEventListener("mousemove",move);
            let bucket = document.querySelector("#bucket"); 
            //获取到所有样式为active的li
            let lis = document.querySelectorAll("ul .active");
            lis.forEach(item=>{
                item.classList.remove("active");
                bucket.appendChild(item);
            });
            
            //鼠标放下时清除上一个div
            div.remove();//使用removeChild有可能还未创建div
        },{
            once:true
        });
        e.preventDefault();
    });
}
</script>
</body>
</html>

效果:

发布了95 篇原创文章 · 获赞 115 · 访问量 12万+

猜你喜欢

转载自blog.csdn.net/qq_34569497/article/details/99681781