好久没有更新博客了,感觉有些手生了,最近换了工作,有传统软件公司跳槽到互联网公司,由原来主做后端,兼职前端变成了全职前端;第一次进入互联网公司,感觉和传统软件公司或技术服务类公司相比,技术范围很浓,大家对技术更有追求,学习更主动,我很喜欢这种气氛,虽然很忙,但是感觉很充实,以后前端这部分开启,把所学所得记录下来,为自己也为分享,本篇作为开篇,聊聊鼠标框选操作。
1、应用描述
对于鼠标框选,网上已有粗糙的实现方案,这里也注重思路和方案,逐步对代码进行完善。
鼠标框选,其实是对传统选择的一个升级,想象这样一种场景,用户选择单选框/复选框,多行多列等,如果需要用户单击选择,数量越多,用户体验越差,对于用户来说,越简单的操作,体验越好,如果通关鼠标拖动,产生一个框选区域,可以对框选区域内所有元素进行操作,也不失为批量操作的一个选择。
2、实现思路
所谓框选,直白一点就是绘制一个矩形,而绘制矩形的方式有很多,比如创建一个div/基于cavans绘制一个矩形,创建一个svg矩形,这里我们以最简单的一种方式来实现,基于div来实现。
整个过程如下:
1、创建一个div
2、添加到dom
3、监听mousemove事件,重绘div
如果如果只是简单框选,该过程已ok,如果需要框选区高亮,则过程需要如下重构:
1、创建一个div作为选择框,创建四个div分表作为上、下、左、右四个mask
2、添加div到dom,同时添加mask到dom
3、监听mousemove事件,重绘div和mask
3、代码框架
今天作为上篇,仅提出实现思路及未经测试的非伪代码,下篇会加入继续完善,基本代码框架如下:
1 ; (function ($) { 2 3 /** 4 * 坐标点 5 * @param {*} x 6 * @param {*} y 7 */ 8 function Point(x, y) { 9 this.x = x; 10 this.y = y; 11 } 12 /** 13 * 框选构造函数 14 * @param {*} rangEl 容器元素 15 * @param {*} options 选择项 16 */ 17 function FrameSelection(rangEl, options) { 18 this._rangeEl = rangEl; 19 this._options = $.extend({}, { callback: function () { } }, options); 20 21 this.init(); 22 } 23 /** 24 * 框选初始化 25 */ 26 FrameSelection.prototype.init = function () { 27 this.unbind(); 28 this.bind(); 29 } 30 /** 31 * 解除事件绑定 32 */ 33 FrameSelection.prototype.unbind = function () { 34 var $rangEl = $(this._rangeEl); 35 $rangEl.off('mousedown'); 36 $rangEl.off('mousemove'); 37 $rangEl.off('mouseup'); 38 } 39 /** 40 * 绘制接口 41 */ 42 FrameSelection.prototype.render = function (p1, p2) { 43 this._renderMask(); 44 this._renderRect(); 45 46 typeof this._options.callback === 'function' && this._options.callback(); 47 } 48 49 /** 50 * 创建遮罩层 51 */ 52 FrameSelection.prototype._renderMask = function (p1, p2) { 53 this.create('div.mask', 4, $divs => { 54 //TODO:计算位置 55 //渲染到dom中 56 $divs.appendTo($(this._rangeEl)); 57 }) 58 } 59 /** 60 * 创建矩形选框 61 */ 62 FrameSelection.prototype._renderRect = function (p1, p2) { 63 this.create('div.rect', 1, $div => { 64 //TODO:计算位置 65 //渲染到dom中 66 $div.appendTo($(this._rangeEl)); 67 68 }); 69 } 70 /** 71 * 创建元素 72 */ 73 FrameSelection.prototype.create = function (eleDes, n, callback) { 74 var desArr = eleDes.split('.'); 75 var eleName = desArr[0], className = desArr[1] || '', eles = ''; 76 77 for (var i = 0; i < n; i++) { 78 eles += '<${eleName} class="${className}"><${eleName}/>'; 79 } 80 81 callback && typeof callback === "function" && callback($(eles)); 82 83 } 84 /** 85 * 注册事件绑定 86 */ 87 FrameSelection.prototype.bind = function () { 88 var $rangEl = $(this._rangeEl); 89 var self = this; 90 $rangEl.bind('mousedown', function (event) { 91 var start = new Point(event.pageX, event.pageY); 92 //绑定mousedown事件, 93 94 $rangEl.bind('mousemove', function (e) { 95 var end = new Point(e.pageX, e.pageY); 96 //绘制 97 self.render(start, end); 98 99 })100 })101 }102 })(window.jQuery);
说明:为了dom操作简单,这里假设以引入jquery,代码属于可以作为伪代码阅读,未经过测试,只是基本框架,下篇会进行完善,敬请期待。。。