# js实现框选(依赖jquery)

js实现框选(依赖jquery)

这个例子的关键之处有两点选择框和盒子与选择框相交的算法

这里写图片描述

1、选择框相关算法

选择框有如图所示的四种拖动情况。最简单的情况是第一种情况从起点向右下角拖动这种情况只需要设置选择框的宽高就行。另外三种情况的话不仅要设置宽带高度还需要设置选择框的坐标位置。

  • 四种情况都需要设置宽高则在最开始为其设置宽高
  • x方向上,当向右不管,向左的话将起点的x坐标向左移动宽度的距离
  • y方向上,当向下不管,向上的话则将起点的y坐标想上移动高度的距离

这里写图片描述

核心代码:

    //选择框核心代码
    //x,y为当前鼠标的位置
    function resizeToPoint(x,y){
        var width = Math.abs(x-startX);
        var height = Math.abs(y-startY);
        rector.width(width);
        rector.height(height);
        //当鼠标x方向上为向左拖动 设置left位置
        if(x<startX){
            rector.css({
                left:(startX-width)+'px',
            });
        }
        //当鼠标y方向上为向上拖动 设置top位置
        if(y<startY){
            rector.css({
                top:(startY-height)+'px',
            });
        }
    }

2、矩形相交算法

  • 由下图可看出只要确定一个点在另外一个点的内部即可证明相交,这个点的关系:x:x1< x< x2,y:y1< y< y2

  • 对于点(x1’,y1’)的判断是:(x1< x1’< x2)&&(y1< y1’< y2)
    这样一个点一个点的判断似乎太麻烦了。其实我们只需要判断两个矩形不想交取反就行。只要y1’>y2 就表示红色框在蓝色框下方相反y1>y2’证明蓝色框在红色框下面。在x方向上同样的道理。只要满足x方向上不重合并且y方向上不重合就表示矩形不想交。所以不相交的公式如下:

    • (x1>x2’ || x1’>x2) || (y1>y2’ || y1’>y2)

这里写图片描述

    /**
     *核心相交算法
     * @param rect1{x1,y1,x2,y2}
     * @param rect2 {x1,y1,x2,y2}
     */
    function isCross(rect1,rect2){
        var xNotCross=true;//x方向上不重合
        var yNotCross = true;//y方向上不重合
        xNotCross =((rect1.x1>rect2.x2) || (rect2.x1>rect1.x2));
        yNotCross =  ((rect1.y1>rect2.y2) || (rect2.y1>rect1.y2));
        return !(xNotCross || yNotCross);
    }

3、源码

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
    <script src="http://127.0.0.1/bower_components/jquery/dist/jquery.js"></script>
    <style>
        .dragbox {
            float: left;
            list-style: none;
            width: 100px;
            height: 100px;
            border: 1px solid;
            margin: 20px;
        }
        .dragbox, img {
            -webkit-user-select: none;
            -webkit-user-drag: none;
        }
        .draging {
            background-color: aquamarine;;
        }
        .selected{
            background-color: #FF0;
        }
        * {
            cursor: default;
        }
    </style>
</head>
<body>

<ul style="display: inline-block">
    <li class="dragbox" id="box1">1</li>
    <li class="dragbox" id="box2">2</li>
    <li class="dragbox" id="box3">3</li>
    <li class="dragbox" id="box4">4</li>
    <li class="dragbox" id="box5">5</li>
    <li class="dragbox" id="box6">6</li>
    <li class="dragbox" id="box7">7</li>
    <li class="dragbox" id="box8">8</li>
    <li class="dragbox" id="box9">9</li>
    <li class="dragbox" id="box10">10</li>
    <li class="dragbox" id="box11">11</li>
    <li class="dragbox" id="box12">12</li>
    <li class="dragbox" id="box13">13</li>
    <li class="dragbox" id="box14">14</li>
    <li class="dragbox" id="box15">15</li>
    <li class="dragbox" id="box16">16</li>
    <li class="dragbox" id="box17">17</li>
    <li class="dragbox" id="box18">18</li>
    <li class="dragbox" id="box19">19</li>
    <li class="dragbox" id="box20">20</li>
</ul>
    <div id="selectionRect" style="position: absolute;background-color: rgba(137,189,189,0.5);border:1px solid rgb(137,189,189);;"></div>
</body>
</html>

<script>
    var rector = $('#selectionRect');
    //拖选起点
    var startX = 0;
    var startY = 0;

    //选择框核心代码
    function resizeToPoint(x,y){
        var width = Math.abs(x-startX);
        var height = Math.abs(y-startY);
        rector.width(width);
        rector.height(height);
        //当鼠标x方向上为向左拖动 设置left位置
        if(x<startX){
            rector.css({
                left:(startX-width)+'px',
            });
        }
        //当鼠标y方向上为向上拖动 设置top位置
        if(y<startY){
            rector.css({
                top:(startY-height)+'px',
            });
        }
    }

    /**
     *核心相交算法
     * @param rect1{x1,y1,x2,y2}
     * @param rect2 {x1,y1,x2,y2}
     */
    function isCross(rect1,rect2){
        var xNotCross=true;//x方向上不重合
        var yNotCross = true;//y方向上不重合
        xNotCross =((rect1.x1>rect2.x2) || (rect2.x1>rect1.x2));
        yNotCross =  ((rect1.y1>rect2.y2) || (rect2.y1>rect1.y2));
        return !(xNotCross || yNotCross);
    }
    /**
     *获取元素的矩形的起始点坐标与其对角点坐标
     * @param $el
     * @return {x1,y1,x2,y2}
     */
    function getRect($el){
        var x1 = $el.offset().left;
        var y1 = $el.offset().top;
        var x2 = x1 +$el.outerWidth();
        var y2 = y1+$el.outerHeight();
        return {x1,x2,y1,y2};
    }

    //框选处理 如果元素与选择框相交则设置样式
    function handleRectSelection(){
        var selectionReact = getRect(rector);
        $('.dragbox').each(function(){
            var rect = getRect($(this));
            if(isCross(selectionReact,rect)){
                $(this).addClass('selected');
            }else{
                $(this).removeClass('selected');
            }
        });
    }

$(window).on({
    mousemove:function(e){
        if(e.which===1){
            rector.show();
            resizeToPoint(e.pageX, e.pageY);
            handleRectSelection();
        }
    },
    mouseup:function(){
        rector.hide();
    },
    mousedown:function(e){
        startX = e.pageX;
        startY = e.pageY;
        rector.css({
            top: startY+'px',
            left: startX+'px'
        });
    }
});
</script>
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值