主要用来实现下图的效果,通过鼠标左键按住框选元素,将框选的元素返回
很少用js写前端了,最近项目需要,用的Js来实现功能,有不足的地方还请帮忙指出
/**
* 矩形框选页面上元素并回填
* 通过改变屏幕的pageStatus来实现屏幕上的鼠标事件的操作
* 在页面加载的时候给鼠标绑定事件,当pageStatus为指定的状态时,则可以执行事件对应的操作
* $("#rightspan")[0] 指的也是页面对象,主要用来获取页面已经滚动的距离
*/
function onSelectPluginClone() {
//这里的y1 y2 指的都是在所有页面上的位置,不是屏幕上的位置
let x1, y1, x2, y2;
//表示的是所有页面上的元素
let $content = $("#content");
// 1、鼠标点击确定起始坐标并准备绘制选框
$content.on("mousedown", function (e) {
// 1、判断页面状态 如果是指定的状态表示进入框选状态,否之不管
if (window.pageStatus !== "selectable") {
return;
}
// 2、记录选区起始坐标
x1 = e.clientX;
//选框开始的位置应该为当前屏幕的距离+已经滚动的距离
y1 = e.clientY + $("#rightspan")[0].scrollTop;
// 3、创建选区 创建该div为选区元素,主要用来显示一个框告知用户框选的范围,目前是隐藏状态在移动时恢复显示
$content.append(`<div id="area" style="display: none;position: absolute;z-index: 9999999;border: 2px solid blue;"></div>`);
// 4、阻止文字拖拽和选择
e.preventDefault();
});
// 2、鼠标移动调整选框位置和宽高
$content.on("mousemove", function (e) {
// 1、判断页面状态 x1为空或x2为空表示选区还未创建,起始位置还未确定,暂时不执行
if (window.pageStatus !== "selectable" || !x1 || !y1) {
return;
}
//当光标到距离屏幕底部50px的距离则屏幕往下滚动
if (e.clientY >= window.screen.height - 50) {
$("#rightspan")[0].scrollTop += (e.clientY - window.screen.height + 75)
}
// 2、调整选框位置和宽高
//解释:e.clientY + $("#rightspan")[0].scrollTop - y1
//选框高度为 当前鼠标的位置+已经滚动的距离-选框的起始位置
let width = Math.abs(e.clientX - x1),
height = Math.abs(e.clientY + $("#rightspan")[0].scrollTop - y1);
//这里用min取小值主要为了可能框选的位置是从往左上框选
let top = Math.min(e.clientY + $("#rightspan")[0].scrollTop, y1),
left = Math.min(e.clientX, x1);
let $area = $("#area");
//如果父元素已经改变过位置,则需要减去父元素的位置
let parentTop = parseFloat($("#rightspan").css("top"));
let parentLeft = parseFloat($("#rightspan").css("left"));
top -= parentTop;
left -= parentLeft
$area.css("width", width + "px");
$area.css("height", height + "px");
$area.css("left", left + "px");
$area.css("top", top + "px");
$area.show();
});
// 3、鼠标松开确定结束结点,并处理选区中的组件
$content.on("mouseup", function (e) {
// 1、判断页面状态
if (window.pageStatus !== "selectable" || !x1 || !y1) {
return;
}
// 2、记录结束坐标,保证x1 < x2, y1 < y2 如果选框在起始点左上位置,
// 则当前选框结束位置变为开始位置,开始位置作为结束位置
if (e.clientX > x1) {
x2 = e.clientX;
} else {
x2 = x1;
x1 = e.clientX;
}
//如果当前鼠标的位置+滚动的距离 大于开始的位置,则表示是往右下框选,正常获取选框
if (e.clientY + $("#rightspan")[0].scrollTop > y1) {
y2 = e.clientY + $("#rightspan")[0].scrollTop;
} else {
y2 = y1;
y1 = e.clientY + $("#rightspan")[0].scrollTop;
}
handleMouseUp();
});
/**
* 处理鼠标松开事件
*/
function handleMouseUp() {
// 1、获取区间内所有组件,当组件太多的时候可能会出现效率问题
let plugins = Array.from($content.find(".ui-plugin"));
let rightSpan = $("#rightspan")[0];
// 2、筛选出有效组件
let selectedPlugins = null
selectedPlugins = plugins.filter(plugin => {
// 需要减去滚动距离
let left = offset(plugin, "left") - rightSpan.scrollLeft,
top = offset(plugin, "top");
let width = plugin.offsetWidth,
height = plugin.offsetHeight;
//组件到左边的距离在起始x1内,到顶端的距离在起始y1内
//且组件到左边的距离+组件本身的宽度在框选结束x2内
//且组件到顶部的距离+组件本身的高度在框选结束y2内
//表示该组件位于框选的位置内,将组件加入
return left >= x1 && top >= y1 && (left + width) <= x2 && (top + height) <= y2;
});
// 3、重置坐标,并删除选区
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
$("#area").remove();
// 4、处理组件
handleSelectedPlugins(selectedPlugins);
// 5、更改页面状态
$(".content").removeClass("selectable");
$("#page-container").removeClass("top");
window.pageStatus = "edit";
}
/**
* 处理选中的组件
* @param plugins
*/
function handleSelectedPlugins(plugins) {
if (plugins.length < 1) {
return
}
//对选中的组件集合plugins进行操作
}
/**
* 获取元素距离左边界和上边界的实际值
* @param ele
* @param leftOrTop
*/
function offset(ele, leftOrTop) {
// offsetLeft Or offsetTop
let offsetDir = "offset" + leftOrTop[0].toUpperCase() + leftOrTop.substring(1);
//获取元素的 左 | 上的距离
let realValue = ele[offsetDir];
//遍历元素的父元素,获得元素的父元素到外层的距离
let parent = ele.offsetParent;
while (parent !== null) {
realValue += parent[offsetDir];
parent = parent.offsetParent;
}
return realValue;
}
}