js实现鼠标拖拽多选功能

最近做了一个用js实现鼠标拖拽多选的功能,于是整理了一下思路,写了一个小demo:
遮罩出现:
clipboard.png
被遮罩盖住的,即为选中的块(背景色为粉色)
clipboard.png
下面是具体代码,注释已在文中,与大家交流。

<!DOCTYPE html>
<html>
<head>
    <title>鼠标拖拽多选功能</title>
    <script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
    <style type="text/css">
        *{
            box-sizing:border-box;
        }
        ul{
            width:500px;
            height:auto;
            margin:0;
            padding:20px;
            font-size: 0;
            /*需设置定位*/
            position:relative;
        }
        li{
            width:70px;
            height:70px;
            margin:10px;
            padding:0;
            display:inline-block;
            vertical-align: top;
            font-size: 13px;
            border:1px solid #d9d9d9;
        }
        #moveSelected{
            position:absolute;
            background-color: blue;
            opacity:0.3;
            border:1px dashed #d9d9d9;
            top:0;
            left:0;
        }
        .selected{
            background-color: pink;
        }
    </style>
</head>
<body>
    <ul class="list">
        <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>
        <li>14</li>
        <li>15</li>
        <li>16</li>
        <li>17</li>
        <li>18</li>
        <li>19</li>
        <li>20</li>
        <li>21</li>
        <li>22</li>
        <!-- 鼠标拖拽出的遮罩 (定位为  position:absolute)-->
        <!-- 遮罩最好是在绑定了mouseover事件的元素内部,并且不要阻止遮罩的冒泡事件。这样鼠标移到了遮罩上面,依然可以利用冒泡执行父元素的mouseover事件,就不会出现遮罩只能扩大,不能缩小的情况了(亲自试过) -->
        <div id="moveSelected"></div>
    </ul>
</body>
</html>
<script type="text/javascript">
    $(document).ready(function(){
        let moveSelected=$('#moveSelected')[0];
        let flag=false;//是搜开启拖拽的标志
        let oldLeft=0;//鼠标按下时的left,top
        let oldTop=0;
        let selectedList=[];//拖拽多选选中的块集合

        // 鼠标按下时开启拖拽多选,将遮罩定位并展现
        $(".list").mousedown(function(event) {
            flag=true;
            moveSelected.style.top=event.pageY+'px';
            moveSelected.style.left=event.pageX+'px';
            oldLeft=event.pageX;
            oldTop=event.pageY;
            event.preventDefault();  // 阻止默认行为
            event.stopPropagation(); // 阻止事件冒泡
        });
        // 鼠标移动时计算遮罩的位置,宽 高
        $(".list").mousemove(function(event) {
            if(!flag) return;//只有开启了拖拽,才进行mouseover操作
            if(event.pageX<oldLeft){//向左拖
                moveSelected.style.left=event.pageX+'px';
                moveSelected.style.width=(oldLeft-event.pageX)+'px';
            }else{
                moveSelected.style.width=(event.pageX-oldLeft)+'px';
            }
            if(event.pageY<oldTop){//向上
                moveSelected.style.top=event.pageY+'px';
                moveSelected.style.height=(oldTop-event.pageY)+'px';
            }else{
                moveSelected.style.height=(event.pageY-oldTop)+'px';
            }
            event.preventDefault();  // 阻止默认行为
            event.stopPropagation(); // 阻止事件冒泡
        });
        //鼠标抬起时计算遮罩的right 和 bottom,找出遮罩覆盖的块,关闭拖拽选中开关,清除遮罩数据
        $(".list").mouseup(function(event) {
            moveSelected.style.bottom=Number(moveSelected.style.top.split('px')[0])+Number(moveSelected.style.height.split('px')[0]) + 'px';
            moveSelected.style.right=Number(moveSelected.style.left.split('px')[0])+Number(moveSelected.style.width.split('px')[0])+'px';
            findSelected();
            flag=false;
            clearDragData();
            event.preventDefault();  // 阻止默认行为
            event.stopPropagation(); // 阻止事件冒泡
        });
        $(".list").mouseleave(function(event) {
            flag=false;
            moveSelected.style.width=0;
            moveSelected.style.height=0;
            moveSelected.style.top=0;
            moveSelected.style.left=0;
            event.preventDefault();  // 阻止默认行为
            event.stopPropagation(); // 阻止事件冒泡
        });
        function findSelected(){
            let blockList=$('.list').find('li');
            for(let i=0;i<blockList.length;i++){
                //计算每个块的定位信息
                let left=$(blockList[i]).offset().left;
                let right=$(blockList[i]).width()+left;
                let top=$(blockList[i]).offset().top;
                let bottom=$(blockList[i]).height()+top;
                //判断每个块是否被遮罩盖住(即选中)
                let leftFlag=moveSelected.style.left.split('px')[0]<=left && left<=moveSelected.style.right.split('px')[0];
                let rightFlag=moveSelected.style.left.split('px')[0]<=right && right<=moveSelected.style.right.split('px')[0];
                let topFlag=moveSelected.style.top.split('px')[0]<=top && top<=moveSelected.style.bottom.split('px')[0];
                let bottomFlag=moveSelected.style.top.split('px')[0]<=bottom && bottom<=moveSelected.style.bottom.split('px')[0];
                if((leftFlag || rightFlag) && (topFlag || bottomFlag)){
                    selectedList.push(blockList[i]);
                    $(blockList[i]).addClass('selected');
                }
            }
            console.log(selectedList);
        }
        function clearDragData(){
            moveSelected.style.width=0;
            moveSelected.style.height=0;
            moveSelected.style.top=0;
            moveSelected.style.left=0;
            moveSelected.style.bottom=0;
            moveSelected.style.right=0;
        }
    });
</script>
  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CascaderPanel 组件实现多选功能的方法是通过在组件中添加一个多选框来实现的。具体实现步骤如下: 1. 在 CascaderPanel 组件中添加一个多选框,例如: ```html <el-checkbox v-model="multiple" @change="handleMultipleChange">多选</el-checkbox> ``` 其中,`multiple` 表示当前是否多选,`handleMultipleChange` 是多选框值改变时的回调函数。 2. 在 CascaderPanel 组件的 `data` 中添加一个 `checkedKeys` 属性,用于保存已选中的值。例如: ```js data() { return { checkedKeys: [], // ... }; } ``` 3. 在 CascaderPanel 组件中,当用户点击菜单项时,需要根据 `multiple` 属性的值来判断是单选还是多选。如果是单选,直接更新 `value` 属性;如果是多选,需要更新 `checkedKeys` 属性。例如: ```js handleItemClick(option) { if (this.multiple) { const index = this.checkedKeys.indexOf(option.value); if (index >= 0) { this.checkedKeys.splice(index, 1); } else { this.checkedKeys.push(option.value); } } else { this.$emit('input', option.value); this.$emit('change', option.value); } } ``` 在多选模式下,通过判断当前值是否已经在 `checkedKeys` 中,来实现添加或删除值的操作。 4. 在 CascaderPanel 组件中,需要根据 `multiple` 属性的值来判断是否显示已选中的值。当 `multiple` 为 `true` 时,需要通过 `checkedKeys` 属性来展示已选中的值,例如: ```html <template v-if="multiple"> <div class="el-cascader-panel__tags"> <el-tag v-for="key in checkedKeys" :key="key" closable @close="handleTagClose(key)"> {{ getCheckedNodeLabel(key) }} </el-tag> </div> </template> ``` 其中,`getCheckedNodeLabel` 函数用于获取已选中的节点的标签文本。 5. 在 CascaderPanel 组件中,需要在多选框值改变时,根据 `multiple` 属性的值来更新已选中的值。例如: ```js handleMultipleChange(value) { if (!value) { this.checkedKeys = []; } } ``` 当多选框从选中状态变为未选中状态时,需要清空已选中的值。 通过上述步骤,就可以在 CascaderPanel 组件中实现多选功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值