2023年6月20日发(作者:)
html5实现⿏标框选,使⽤原⽣js编写⼀个简单的框选功能⽅法今天我们来聊⼀下怎么使⽤原⽣javascript编写⼀个简单的框选功能。需求描述⿏标左键按下不放,移动⿏标出现矩形选框;⿏标左键松开,根据上边出现的矩形选框统计选框范围内的DOM元素;嗯...上边的功能描述看着是挺简单的,但实现起来也还是会有些地⽅需要斟酌思考的。⽐如,如果我们的框选范围不是,⽽是某⼀个div⾥边进⾏框选呢?⽽现实开发过程中,我们会遇上的应该就是第⼆种情况。怎么实现⼆话不说,咱们动⼿写代码吧!因为更好的兼容性,这⾥就避免了⼀些ES6的语法,如果是⽤的其他框架来写的话,代码上相应的也要做⼀些调整。.fileDiv {display: inline-block;width: 100px;height: 100px;margin: 24px;background-color: blue;}添加⿏标事件监听由于js⾃⾝并没有带有⿏标点击按住不放这样⼦的事件,这⾥我们不仅需要检测⿏标左键点击按下,还要加⼀个定时器来检测⿏标是否按住不放了。(function () {// 定时器idvar mouseStopId;// 是否开启框选功能var mouseOn = false;// ⽤来存放⿏标点击初始位置var startX = 0;var startY = 0;// 添加⿏标按下监听事件ntListener('mousedown', function (e) {// 阻⽌事件冒泡clearEventBubble(e);// 判断是否为⿏标左键被按下if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;}, 300); // 间隔300毫秒后执⾏,判定这时候⿏标左键被按住不放});// 添加⿏标移动事件监听ntListener('mousemove', function (e) {// 如果并⾮框选开启,退出if (!mouseOn) return;// 阻⽌事件冒泡clearEventBubble(e);// 处理⿏标移动// codes});// 添加⿏标点击松开事件监听ntListener('mouseup', function (e) {// 阻⽌事件冒泡clearEventBubble(e);// 处理⿏标点击松开// codes});function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();添加框选可视化元素框选可视化元素⽰意图我们有了事件监听还不够,为了更好的交互效果,我们需要⼀个随时跟随着⿏标移动的框选框元素,⽤于让⽤户随时感知框选范围。(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;ntListener('mousedown', function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;// 创建⼀个框选元素var selDiv = Element('div');// 给框选元素添加css样式,这⾥使⽤绝对定位t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;';// 添加 = 'selectDiv';Child(selDiv);// 根据起始位置,添加定位 = startX + 'px'; = startY + 'px';}, 300);});ntListener('mousemove', function (e) {if (!mouseOn) return;clearEventBubble(e);// 获取当前坐标var _x = X;var _y = Y;// 根据坐标给选框修改样式var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';// 如果需要更直观⼀点的话,我们还可以在这⾥进⾏对框选元素覆盖到的元素进⾏修改被框选样式的修改。});ntListener('mouseup', function (e) {clearEventBubble(e);});function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();添加⿏标松开事件监听元素是否被选中⽰意图我们没有在⿏标移动的时候去实时统计被框选到的DOM元素,如果需要实时统计或者实时修改被选择的DOM元素的样式,以便更准确的让⽤户感知到被框选的内容的话,可以选择在mousemove事件⾥边去实现以下代码:(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;edown = function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;var selDiv = Element('div');t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;'; = 'selectDiv';Child(selDiv); = startX + 'px'; = startY + 'px';}, 300);}emove = function (e) {if (!mouseOn) return;clearEventBubble(e);var _x = X;var _y = Y;var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';};// 添加⿏标松开事件监听eup = function (e) {if (!mouseOn) return;clearEventBubble(e);var selDiv = mentById('selectDiv');var fileDivs = mentsByClassName('fileDiv');var selectedEls = [];// 获取参数var l = Left;var t = Top;var w = Width;var h = Height;for (var i = 0; i < ; i++) {var sl = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft;var st = fileDivs[i].offsetHeight + fileDivs[i].offsetTop;if (sl > l && st > t && fileDivs[i].offsetLeft < l + w && fileDivs[i].offsetTop < t + h) {// 该DOM元素被选中,进⾏处理(fileDivs[i]);}}// 打印被选中DOM元素(selectedEls);// 恢复参数y = 'none';mouseOn = false;};function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();这⾥判断⼀个元素是否被选中采⽤的判断条件是:该DOM元素的最右边(fileDiv[i].offsetLeft + fileDiv[i].offsetWidth)是否要⽐选框元素最左边(Left)的位置要⼩;该DOM元素的最下边(fileDiv[i].offsetTop + fileDiv[i].offsetHeight)是否要⽐选框元素的最上边(Top)的位置要⼤;该DOM元素的最左边(fileDiv[i].offsetLeft)是否要⽐选框元素的最后边(Left + Width)的位置数值要⼩;该DOM元素的最上边(fileDiv[i].offsetTop)是否要⽐选框元素的最下边(Top + Height)的位置数值要⼩;满⾜了以上四个条件,即可判别为该DOM元素被选中了。实际应⽤上边的例⼦,举得有些过于简单了。实际的开发当中,框选的范围往往不可能是整个,⽽是某⼀个具体的有特定宽度跟⾼度限制的元素。这个时候,就还需要考虑这个框选容器元素造成的定位偏差,以及容器内元素过多,出现滚动条的情况了。乍⼀看,上边的情况需要考虑的因素多了不少,⽐较容易乱。我这⾥采⽤的⽅法是修改坐标系的⽅式来实现上边描述的功能。上⽂我们已经实现了在整个页⾯左上⾓顶点作为坐标原点来实现框选功能,这时候我们需要修改坐标原点为框选容器的左上⾓顶点作为坐标原点即可。换⾔之,就是修改mousedown跟mousemove事件时,初始位置由原来的X跟Y修改为X -Left + Left跟Y - Top + Top。坐标更改shi'yi'turegionbody {margin: 0;padding: 0;}#selectContainer {position: relative;width: 400px; /* 演⽰宽⾼与位置 */height: 400px;top: 200px;left: 200px;border: 1px solid #eee;overflow: hidden;overflow-y: auto;}.fileDiv {display: inline-block;width: 100px;height: 100px;margin: 24px;background-color: #0082CC;}(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;edown = function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;// 获取容器元素var selectContainer = mentById('selectContainer');// 调整坐标原点为容器左上⾓startX = X - Left + Left;startY = Y - Top + Top;var selDiv = Element('div');t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;'; = 'selectDiv';// 添加框选元素到容器内mentById('selectContainer').appendChild(selDiv); = startX + 'px'; = startY + 'px';}, 300);}emove = function (e) {if (!mouseOn) return;clearEventBubble(e);var selectContainer = mentById('selectContainer');var _x = X - Left + Left;var _y = Y - Top + Top;var _H = Height;// ⿏标移动超出容器内部,进⾏相应的处理// 向下拖拽if (_y >= _H && Top <= _H) {Top += _y - _H;}// 向上拖拽if (Y <= Top && Top > 0) {Top = (Y - Top);}var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';};eup = function (e) {if (!mouseOn) return;clearEventBubble(e);var selDiv = mentById('selectDiv');var fileDivs = mentsByClassName('fileDiv');var selectedEls = [];var l = Left;var t = Top;var w = Width;var h = Height;for (var i = 0; i < ; i++) {var sl = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft;var st = fileDivs[i].offsetHeight + fileDivs[i].offsetTop;if (sl > l && st > t && fileDivs[i].offsetLeft < l + w && fileDivs[i].offsetTop < t + h) {(fileDivs[i]);}}(selectedEls);y = 'none';mouseOn = false;};function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();使⽤前端框架上边的代码,我们只是在⼀个html⽂件⾥边实现了框选的功能。很多时候,我们会使⽤⼀些前端框架来编写框选的功能(例如,angular,react,polymer之类的前端框架)。这个时候,我们可以利⽤框架⾃⾝的⽣命周期的函数,添加对应的监听事件,然后在mouseup事件⾥移除掉上边这些事件监听,以减少不必要的资源消耗。⽽且,很多时候,组件化的使⽤,使得被框选的元素,往往也是⼀个可重复利⽤的⼩组件,也是需要根据相应的框架的对应的途径获取到对应的DOM元素来获取其属性。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持脚本之家。
2023年6月20日发(作者:)
html5实现⿏标框选,使⽤原⽣js编写⼀个简单的框选功能⽅法今天我们来聊⼀下怎么使⽤原⽣javascript编写⼀个简单的框选功能。需求描述⿏标左键按下不放,移动⿏标出现矩形选框;⿏标左键松开,根据上边出现的矩形选框统计选框范围内的DOM元素;嗯...上边的功能描述看着是挺简单的,但实现起来也还是会有些地⽅需要斟酌思考的。⽐如,如果我们的框选范围不是,⽽是某⼀个div⾥边进⾏框选呢?⽽现实开发过程中,我们会遇上的应该就是第⼆种情况。怎么实现⼆话不说,咱们动⼿写代码吧!因为更好的兼容性,这⾥就避免了⼀些ES6的语法,如果是⽤的其他框架来写的话,代码上相应的也要做⼀些调整。.fileDiv {display: inline-block;width: 100px;height: 100px;margin: 24px;background-color: blue;}添加⿏标事件监听由于js⾃⾝并没有带有⿏标点击按住不放这样⼦的事件,这⾥我们不仅需要检测⿏标左键点击按下,还要加⼀个定时器来检测⿏标是否按住不放了。(function () {// 定时器idvar mouseStopId;// 是否开启框选功能var mouseOn = false;// ⽤来存放⿏标点击初始位置var startX = 0;var startY = 0;// 添加⿏标按下监听事件ntListener('mousedown', function (e) {// 阻⽌事件冒泡clearEventBubble(e);// 判断是否为⿏标左键被按下if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;}, 300); // 间隔300毫秒后执⾏,判定这时候⿏标左键被按住不放});// 添加⿏标移动事件监听ntListener('mousemove', function (e) {// 如果并⾮框选开启,退出if (!mouseOn) return;// 阻⽌事件冒泡clearEventBubble(e);// 处理⿏标移动// codes});// 添加⿏标点击松开事件监听ntListener('mouseup', function (e) {// 阻⽌事件冒泡clearEventBubble(e);// 处理⿏标点击松开// codes});function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();添加框选可视化元素框选可视化元素⽰意图我们有了事件监听还不够,为了更好的交互效果,我们需要⼀个随时跟随着⿏标移动的框选框元素,⽤于让⽤户随时感知框选范围。(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;ntListener('mousedown', function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;// 创建⼀个框选元素var selDiv = Element('div');// 给框选元素添加css样式,这⾥使⽤绝对定位t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;';// 添加 = 'selectDiv';Child(selDiv);// 根据起始位置,添加定位 = startX + 'px'; = startY + 'px';}, 300);});ntListener('mousemove', function (e) {if (!mouseOn) return;clearEventBubble(e);// 获取当前坐标var _x = X;var _y = Y;// 根据坐标给选框修改样式var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';// 如果需要更直观⼀点的话,我们还可以在这⾥进⾏对框选元素覆盖到的元素进⾏修改被框选样式的修改。});ntListener('mouseup', function (e) {clearEventBubble(e);});function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();添加⿏标松开事件监听元素是否被选中⽰意图我们没有在⿏标移动的时候去实时统计被框选到的DOM元素,如果需要实时统计或者实时修改被选择的DOM元素的样式,以便更准确的让⽤户感知到被框选的内容的话,可以选择在mousemove事件⾥边去实现以下代码:(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;edown = function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;startX = X;startY = Y;var selDiv = Element('div');t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;'; = 'selectDiv';Child(selDiv); = startX + 'px'; = startY + 'px';}, 300);}emove = function (e) {if (!mouseOn) return;clearEventBubble(e);var _x = X;var _y = Y;var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';};// 添加⿏标松开事件监听eup = function (e) {if (!mouseOn) return;clearEventBubble(e);var selDiv = mentById('selectDiv');var fileDivs = mentsByClassName('fileDiv');var selectedEls = [];// 获取参数var l = Left;var t = Top;var w = Width;var h = Height;for (var i = 0; i < ; i++) {var sl = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft;var st = fileDivs[i].offsetHeight + fileDivs[i].offsetTop;if (sl > l && st > t && fileDivs[i].offsetLeft < l + w && fileDivs[i].offsetTop < t + h) {// 该DOM元素被选中,进⾏处理(fileDivs[i]);}}// 打印被选中DOM元素(selectedEls);// 恢复参数y = 'none';mouseOn = false;};function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();这⾥判断⼀个元素是否被选中采⽤的判断条件是:该DOM元素的最右边(fileDiv[i].offsetLeft + fileDiv[i].offsetWidth)是否要⽐选框元素最左边(Left)的位置要⼩;该DOM元素的最下边(fileDiv[i].offsetTop + fileDiv[i].offsetHeight)是否要⽐选框元素的最上边(Top)的位置要⼤;该DOM元素的最左边(fileDiv[i].offsetLeft)是否要⽐选框元素的最后边(Left + Width)的位置数值要⼩;该DOM元素的最上边(fileDiv[i].offsetTop)是否要⽐选框元素的最下边(Top + Height)的位置数值要⼩;满⾜了以上四个条件,即可判别为该DOM元素被选中了。实际应⽤上边的例⼦,举得有些过于简单了。实际的开发当中,框选的范围往往不可能是整个,⽽是某⼀个具体的有特定宽度跟⾼度限制的元素。这个时候,就还需要考虑这个框选容器元素造成的定位偏差,以及容器内元素过多,出现滚动条的情况了。乍⼀看,上边的情况需要考虑的因素多了不少,⽐较容易乱。我这⾥采⽤的⽅法是修改坐标系的⽅式来实现上边描述的功能。上⽂我们已经实现了在整个页⾯左上⾓顶点作为坐标原点来实现框选功能,这时候我们需要修改坐标原点为框选容器的左上⾓顶点作为坐标原点即可。换⾔之,就是修改mousedown跟mousemove事件时,初始位置由原来的X跟Y修改为X -Left + Left跟Y - Top + Top。坐标更改shi'yi'turegionbody {margin: 0;padding: 0;}#selectContainer {position: relative;width: 400px; /* 演⽰宽⾼与位置 */height: 400px;top: 200px;left: 200px;border: 1px solid #eee;overflow: hidden;overflow-y: auto;}.fileDiv {display: inline-block;width: 100px;height: 100px;margin: 24px;background-color: #0082CC;}(function () {var mouseStopId;var mouseOn = false;var startX = 0;var startY = 0;edown = function (e) {clearEventBubble(e);if (s !== 1 || !== 1) return;mouseStopId = setTimeout(function () {mouseOn = true;// 获取容器元素var selectContainer = mentById('selectContainer');// 调整坐标原点为容器左上⾓startX = X - Left + Left;startY = Y - Top + Top;var selDiv = Element('div');t = 'position:absolute;width:0;height:0;margin:0;padding:0;border:1px dashed #eee;background-color:#aaa;z-index:1000;opacity:0.6;display:none;'; = 'selectDiv';// 添加框选元素到容器内mentById('selectContainer').appendChild(selDiv); = startX + 'px'; = startY + 'px';}, 300);}emove = function (e) {if (!mouseOn) return;clearEventBubble(e);var selectContainer = mentById('selectContainer');var _x = X - Left + Left;var _y = Y - Top + Top;var _H = Height;// ⿏标移动超出容器内部,进⾏相应的处理// 向下拖拽if (_y >= _H && Top <= _H) {Top += _y - _H;}// 向上拖拽if (Y <= Top && Top > 0) {Top = (Y - Top);}var selDiv = mentById('selectDiv');y = 'block'; = (_x, startX) + 'px'; = (_y, startY) + 'px'; = (_x - startX) + 'px'; = (_y - startY) + 'px';};eup = function (e) {if (!mouseOn) return;clearEventBubble(e);var selDiv = mentById('selectDiv');var fileDivs = mentsByClassName('fileDiv');var selectedEls = [];var l = Left;var t = Top;var w = Width;var h = Height;for (var i = 0; i < ; i++) {var sl = fileDivs[i].offsetWidth + fileDivs[i].offsetLeft;var st = fileDivs[i].offsetHeight + fileDivs[i].offsetTop;if (sl > l && st > t && fileDivs[i].offsetLeft < l + w && fileDivs[i].offsetTop < t + h) {(fileDivs[i]);}}(selectedEls);y = 'none';mouseOn = false;};function clearEventBubble (e) {if (opagation) opagation();else Bubble = true;if (tDefault) tDefault();else Value = false;}})();使⽤前端框架上边的代码,我们只是在⼀个html⽂件⾥边实现了框选的功能。很多时候,我们会使⽤⼀些前端框架来编写框选的功能(例如,angular,react,polymer之类的前端框架)。这个时候,我们可以利⽤框架⾃⾝的⽣命周期的函数,添加对应的监听事件,然后在mouseup事件⾥移除掉上边这些事件监听,以减少不必要的资源消耗。⽽且,很多时候,组件化的使⽤,使得被框选的元素,往往也是⼀个可重复利⽤的⼩组件,也是需要根据相应的框架的对应的途径获取到对应的DOM元素来获取其属性。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持脚本之家。
发布评论