鼠标框选 下篇
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了鼠标框选 下篇相关的知识,希望对你有一定的参考价值。
接上篇,上篇写了大致的思路,其实还有很多问题,由于没写测试,在运行时出现了很多问题,比如绘制相关代码,会一直添加元素到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 //默认不绘制mask 131 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>
直接保存js代码到frame_selection.js文件,和index.html放在同一目录下,双击浏览器打开即可运行。运行效果如下
以上是关于鼠标框选 下篇的主要内容,如果未能解决你的问题,请参考以下文章