首页 > 代码库 > 鼠标框选 下篇

鼠标框选 下篇

接上篇,上篇写了大致的思路,其实还有很多问题,由于没写测试,在运行时出现了很多问题,比如绘制相关代码,会一直添加元素到dom,这主要因为我在考虑元素绘制和插入dom没有分开处理,本次主要增加了计算和绘制的代码逻辑,逻辑中有些代码还是需要优化的,比如dom访问次数过多,绘制过程做节流处理等,有需要各位自行优化即可,为了操作方便,直接封装成了jQuery插件。

完整代码如下,解释可直接看注释部分:

  1 ; (function ($) {  2   3     $.fn.frameSelection = function (options) {  4         var defaultOpts = {  5             callback: function () { },  6             mask: false,  7             done: function (result) { console.log(result) }  8         };  9         var options = $.extend({}, defaultOpts, options); 10         new FrameSelection($(this), options); 11     } 12     /** 13      * 坐标点 14      * @param {*} x  15      * @param {*} y  16      */ 17     function Point(x, y) { 18         this.x = x; 19         this.y = y; 20     } 21     /** 22      * 框选构造函数 23      * @param {*} $rangeEl 容器元素 24      * @param {*} options 选择项 25      */ 26     function FrameSelection($rangeEl, options) { 27         this.$rangeEl = $rangeEl; 28         this.options = options; 29  30         this.init(); 31     } 32     /** 33      * 框选初始化 34      */ 35     FrameSelection.prototype.init = function () { 36         this.unbind(); 37         this.bind(); 38     } 39     /** 40      * 解除事件绑定 41      */ 42     FrameSelection.prototype.unbind = function () { 43  44         this.$rangeEl.off(‘mousedown‘); 45         this.$rangeEl.off(‘mousemove‘); 46         this.$rangeEl.off(‘mouseup‘); 47     } 48     /** 49      * 绘制接口 50      */ 51     FrameSelection.prototype.render = function (p1, p2) { 52         this.options.mask && this.renderMask(p1, p2); 53         this.renderRect(p1, p2); 54     } 55     /** 56      * 清理元素 57      */ 58     FrameSelection.prototype.clear = function () { 59         this.$rangeEl.find(‘.rect,.mask‘).remove(); 60     } 61  62     /** 63      * 创建遮罩层 64      */ 65     FrameSelection.prototype.renderMask = function (p1, p2) { 66         var $rect = this.$rangeEl.find(‘div.rect‘); 67         var $top = this.$rangeEl.find(‘div.mask:eq(0)‘), 68             $left = this.$rangeEl.find(‘div.mask:eq(1)‘), 69             $right = this.$rangeEl.find(‘div.mask:eq(2)‘), 70             $bottom = this.$rangeEl.find(‘div.mask:eq(3)‘); 71  72         $top.css({ 73             top: this.$rangeEl.css(‘top‘), 74             left: this.$rangeEl.css(‘left‘), 75             width: this.$rangeEl.width(), 76             height: $rect.css(‘top‘) 77         }); 78  79         $left.css({ 80             top: $rect.css(‘top‘), 81             left: $top.css(‘left‘), 82             width: $rect.css(‘left‘), 83             height: $rect.height() 84         }); 85  86         $right.css({ 87             top: $rect.css(‘top‘), 88             left: $left.width() + $rect.width(), 89             width: this.$rangeEl.width() - ($left.width() + $rect.width()), 90             height: $left.height() 91         }); 92  93         $bottom.css({ 94             top: $top.height() + $left.height(), 95             left: this.$rangeEl.css(‘left‘), 96             width: $top.width(), 97             height: this.$rangeEl.height() - ($top.height() + $left.height()) 98         }); 99 100     }101     /**102      * 创建矩形选框103      */104     FrameSelection.prototype.renderRect = function (p1, p2) {105         var $rect = this.$rangeEl.find(‘div.rect‘);106 107         $rect.css({108             top: Math.min(p1.y, p2.y),109             left: Math.min(p1.x, p2.x),110             width: Math.abs(p1.x - p2.x),111             height: Math.abs(p1.y - p2.y)112         })113 114     }115     /**116      * 创建元素117      */118     FrameSelection.prototype.create = function (eleDes, n, callback) {119         var desArr = eleDes.split(‘.‘);120         var eleName = desArr[0], className = desArr[1] || ‘‘, eles = ‘‘;121 122         for (var i = 0; i < n; i++) {123             eles += `<${eleName} class="${className}"></${eleName}>`;124         }125 126         callback && typeof callback === "function" && callback($(eles));127 128     }129     FrameSelection.prototype.createElToDom = function () {130         //默认不绘制mask131         var fn = ($eles) => {132             $eles.appendTo(this.$rangeEl);133         }134         this.options.mask && this.create(‘div.mask‘, 4, fn);135         this.create(‘div.rect‘, 1, fn);136 137         typeof this.options.callback === ‘function‘ && this.options.callback();138     }139     /**140      * 注册事件绑定141      */142     FrameSelection.prototype.bind = function () {143         var self = this;144         this.$rangeEl.bind(‘mousedown‘, function (event) {145             var start = new Point(event.pageX, event.pageY);146             //清理147             self.clear();148             self.createElToDom();149 150             self.$rangeEl.bind(‘mousemove‘, function (e) {151                 var end = new Point(e.pageX, e.pageY);152                 //绘制153                 self.render(start, end);154 155             })156         });157 158         this.$rangeEl.bind(‘mouseup‘, function (e) {159             self.$rangeEl.off(‘mousemove‘);160         })161     }162 })(window.jQuery);

 

直接在html中测试打开即可,css代码未独立处理,直接写入了html文件中,具体代码如下:

技术分享
<!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>frame_selection</title>    <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>    <script src="./frame_selection.js"></script>    <script>        $(document).ready(function(){            $(.container).frameSelection({                mask:true,                callback:function(){                    console.log(rendering!!!);                },                done:function(result){                    console.log(rendering done,result);                }            }) ;        })    </script>    <style>        .container{            width:600px;            height: 400px;            left:0;            top:0;        }        .mask,        .rect {            position: absolute;        }        .mask {            background-color: #000;            opacity: 0.2;        }        .rect {            background-color: #fff;            opacity: 0.1;            border:1px dashed #000;        }    </style></head><body>    <div class="container">    </div></body></html>
View Code

直接保存js代码到frame_selection.js文件,和index.html放在同一目录下,双击浏览器打开即可运行。运行效果如下

技术分享

鼠标框选 下篇