js 实现上下改变父 div 的高度,左右上下动态分割孩子的宽高

3次阅读

共计 8026 个字符,预计需要花费 21 分钟才能阅读完成。

1. 需求
实现父 div 里面 左右,上下动态分割 div,并上下改变父 div 的高度,并且宽和高都是按百分比(如图)。

2. 实现原理
2.1 父布局
<div class=’hj-wrap’>
<div class=”arrow”></div>
</div>

首先一个父 div 为 hj-wrap,相对定位。
一个改变父 div 高度的 arrow,用于上下拖动 , 不能占有位置,所以要绝对定位,并定位到最右下角。
上下拖动的 arrow,当上拖动时,arrow 的父 div 的高度变小,当下拖动时,arrow 的父 div 的高度变大。

2.2 横向布局
<div class=’hj-wrap’>
<div class=”hj-transverse-split-div”>
横 向
<label class=”hj-transverse-split-label”></label>
</div>
<div class=”hj-transverse-split-div”> 横 向 2
<label class=”hj-transverse-split-label”></label>
</div>
<div class=”hj-transverse-split-div”> 横 向 3
<label class=”hj-transverse-split-label”></label>
</div>
<div class=”hj-transverse-split-div”> 横 向 4
<label class=”hj-transverse-split-label”></label>
</div>
<div class=”hj-transverse-split-div”> 横 向 5
</div>
<div class=”arrow”></div>
</div>

每一个横向的 div 为 hj-transverse-split-div 并相对定位,里面有一个拖动改变左右的 label 为 hj-transverse-split-label,不能占有位置,所以要绝对定位,并定位到最右边并高为 100%,最后一个横向的 div 不用 hj-transverse-split-label。
拖动改变左右的 label 时,向左时,label 的父 div 的宽变小,label 的父 div 相邻的 右边的 div 宽度变大。

2.3 竖向布局
<div class=’hj-wrap verticals’>
<div class=”hj-vertical-split-div”> 上
<label class=”hj-vertical-split-label”></label>
</div>
<div class=”hj-vertical-split-div”> 中
<label class=”hj-vertical-split-label”></label>
</div>
<div class=”hj-vertical-split-div”> 下 </div>
<div class=”arrow”></div>
</div>

每一个横向的 div 为 hj-vertical-split-div 并相对定位,里面有一个拖动改变左右的 label 为 hj-vertical-split-label,不能占有位置,所以要绝对定位,并定位到最下边并宽为 100%,最后一个竖向的 div 不用再放 hj-vertical-split-label 的 label。
拖动改变上下的 label 时,向上时,label 的父 div 的高度变小,label 的父 div 相邻的下边的 div 高度变大。

3. js 实现
代码:
/**
* name: split.js
* author: biaochen
* date: 2018-12-26
*
*/
$(function() {
// 鼠标横向、竖向、和改变父高度的上下 操作对象
var thisTransverseObject, thisVerticalObject, thisArrowObject;
// 文档对象
var doc = document;
// 横向分割栏
var transverseLabels = $(“.hj-wrap”).find(“.hj-transverse-split-label”);
// 竖向分割栏
var verticalLabels = $(“.hj-wrap”).find(“.hj-vertical-split-label”);
// 改变父高度的 箭头 div
var parentArrow = $(“.hj-wrap”).find(“.arrow”);

// 设置宽
function setWidth(type) {
if (type === “init”) {
var length = $(“.hj-wrap”).length;
if (length > 0) {
for (var i = 0; i < length; i++) {
var width = $($(“.hj-wrap”)[i])[0].offsetWidth;
var hjDivNums = $($(“.hj-wrap”)[i]).children(“.hj-transverse-split-div”);
// var defaultWidth = Math.floor(100 / hjDivNums.length);
var defaultWidth = Math.floor(width / hjDivNums.length);
$($(“.hj-wrap”)[i])
.children(“.hj-transverse-split-div”)
.width(defaultWidth + “px”);
// .width(defaultWidth + “%”);
}
}
} else {
// 设置百分比
var transverseDivs = $(“.hj-transverse-split-div”)
var widthLength = transverseDivs.length
for (var i = 0; i < widthLength; i++) {
var width = $(transverseDivs[i]).width();
var parentWidth = $(transverseDivs[i])
.parent()
.width();
var rate = (width / parentWidth) * 100 + “%”;
$(transverseDivs[i]).css({width: rate});
}
}
}

// 设置高
function setHeight(type) {
if (type === “init”) {
var verticalsParentDivs = $(“.verticals”);
var parentLengths = verticalsParentDivs.length;
for (var i = 0; i < parentLengths; i++) {
var parentHeight = $(verticalsParentDivs[i]).height();
var childrenNum = $(verticalsParentDivs[i]).children(
“.hj-vertical-split-div”
).length;
var defaultHeight = Math.floor(parentHeight / childrenNum);
// var rate = Math.floor((height / parentHeight)* 100) + ‘%’
var defaultHeight = Math.floor(100 / childrenNum);
$(verticalsParentDivs[i])
.children(“.hj-vertical-split-div”)
.height(defaultHeight + “%”);
// .height(defaultHeight + “px”);
}
} else {
// 设置百分比
var verticalsDivs = $(“.hj-vertical-split-div”);
var heightLength = verticalsDivs.length;
for (var i = 0; i < heightLength; i++) {
var height = $(verticalsDivs[i]).height();
var parentHeight = $(verticalsDivs[i])
.parent()
.height();
var rate = (height / parentHeight) * 100 + “%”;
$(verticalsDivs[i]).css({height: rate});
}
}
}

setWidth(‘init’)
setHeight(“init”);

// 定义一个对象
function PointerObject() {
this.el = null; // 当前鼠标选择的对象
this.clickX = 0; // 鼠标横向初始位置
this.clickY = 0; // 鼠标竖向初始位置
this.transverseDragging = false; // 判断鼠标可否横向拖动
this.verticalDragging = false; // 判断鼠标可否竖向拖动
}
// 横向分隔栏绑定事件
transverseLabels.bind(“mousedown”, function(e) {
thisTransverseObject = new PointerObject();
thisTransverseObject.transverseDragging = true; // 鼠标可横向拖动
thisTransverseObject.el = this;
thisTransverseObject.clickX = e.pageX; // 记录鼠标横向初始位置
});

// 竖向分隔栏绑定事件
verticalLabels.bind(“mousedown”, function(e) {
//console.log(“mousedown”);
thisVerticalObject = new PointerObject();
thisVerticalObject.verticalDragging = true; // 鼠标可竖向拖动
thisVerticalObject.el = this;
thisVerticalObject.clickY = e.pageY; // 记录鼠标竖向初始位置
});
// 上下绑定事件
parentArrow.bind(“mousedown”, function(e) {
//console.log(“mousedown”);
thisArrowObject = new PointerObject();
// thisArrowObject.transverseDragging = true; // 鼠标可横向拖动
thisArrowObject.verticalDragging = true; // 鼠标可竖向拖动
thisArrowObject.el = this;
thisArrowObject.clickY = e.pageY; // 记录鼠标竖向初始位置
});

doc.onmousemove = function(e) {
// 鼠标横向拖动
if (thisTransverseObject != null) {
if (thisTransverseObject.transverseDragging) {
var changeDistance = 0;
if (thisTransverseObject.clickX >= e.pageX) {
// 鼠标向左移动
changeDistance =
Number(thisTransverseObject.clickX) – Number(e.pageX);
if (
$(thisTransverseObject.el)
.parent()
.width() –
changeDistance <
20
) {} else {
$(thisTransverseObject.el)
.parent()
.width(
$(thisTransverseObject.el)
.parent()
.width() – changeDistance
);
$(thisTransverseObject.el)
.parent()
.next()
.width(
$(thisTransverseObject.el)
.parent()
.next()
.width() + changeDistance
);
thisTransverseObject.clickX = e.pageX;
$(thisTransverseObject.el).offset({left: e.pageX});
}
} else {
// 鼠标向右移动
changeDistance =
Number(e.pageX) – Number(thisTransverseObject.clickX);
if (
$(thisTransverseObject.el)
.parent()
.next()
.width() –
changeDistance <
20
) {} else {
$(thisTransverseObject.el)
.parent()
.width(
$(thisTransverseObject.el)
.parent()
.width() + changeDistance
);
$(thisTransverseObject.el)
.parent()
.next()
.width(
$(thisTransverseObject.el)
.parent()
.next()
.width() – changeDistance
);
thisTransverseObject.clickX = e.pageX;
$(thisTransverseObject.el).offset({left: e.pageX});
}
}
$(thisTransverseObject.el).width(2);
}
}
// 鼠标竖向拖动
if (thisVerticalObject != null) {
if (thisVerticalObject.verticalDragging) {
var changeDistance = 0;
if (thisVerticalObject.clickY >= e.pageY) {
// 鼠标向上移动
changeDistance = Number(thisVerticalObject.clickY) – Number(e.pageY);
if (
$(thisVerticalObject.el)
.parent()
.height() –
changeDistance <
20
) {} else {
$(thisVerticalObject.el)
.parent()
.height(
$(thisVerticalObject.el)
.parent()
.height() – changeDistance
);
$(thisVerticalObject.el)
.parent()
.next()
.height(
$(thisVerticalObject.el)
.parent()
.next()
.height() + changeDistance
);
thisVerticalObject.clickY = e.pageY;
$(thisVerticalObject.el).offset({top: e.pageY});
}
} else {
// 鼠标向下移动
changeDistance = Number(e.pageY) – Number(thisVerticalObject.clickY);
if (
$(thisVerticalObject.el)
.parent()
.next()
.height() –
changeDistance <
20
) {} else {
$(thisVerticalObject.el)
.parent()
.height(
$(thisVerticalObject.el)
.parent()
.height() + changeDistance
);
$(thisVerticalObject.el)
.parent()
.next()
.height(
$(thisVerticalObject.el)
.parent()
.next()
.height() – changeDistance
);
thisVerticalObject.clickY = e.pageY;
$(thisVerticalObject.el).offset({top: e.pageY});
}
}
$(thisVerticalObject.el).height(2);
}
}
// 改变父的 高度
if (thisArrowObject != null) {
// 鼠标竖向拖动
if (thisArrowObject.verticalDragging) {
var changeDistance = 0;
if (thisArrowObject.clickY >= e.pageY) {
// 鼠标向上移动
changeDistance = Number(thisArrowObject.clickY) – Number(e.pageY);
if (
$(thisArrowObject.el)
.parent()
.height() –
changeDistance <
50
) {} else {
$(thisArrowObject.el)
.parent()
.height(
$(thisArrowObject.el)
.parent()
.height() – changeDistance
);
thisArrowObject.clickY = e.pageY;
$(thisArrowObject.el).offset({bottom: e.pageY});
}
} else {
// 鼠标向下移动
changeDistance = Number(e.pageY) – Number(thisArrowObject.clickY);
$(thisArrowObject.el)
.parent()
.height(
$(thisArrowObject.el)
.parent()
.height() + changeDistance
);
thisArrowObject.clickY = e.pageY;
$(thisArrowObject.el).offset({bottom: e.pageY});
}
$(thisArrowObject.el).height(10);
}
}
};

$(doc).mouseup(function(e) {
setHeight(“setHeight”);
setWidth(“setWidth”);
// 鼠标弹起时设置不能拖动
if (thisTransverseObject != null) {
thisTransverseObject.transverseDragging = false;
thisTransverseObject = null;
}
if (thisVerticalObject != null) {
thisVerticalObject.verticalDragging = false;
thisVerticalObject = null;
}
if (thisArrowObject != null) {
thisArrowObject.verticalDragging = false;
thisArrowObject = null;
}

e.cancelBubble = true;
});
});
4. 完整代码与效果
效果图:

项目地址:https://github.com/biaochenxuying/split 效果体验地址:https://biaochenxuying.github.io/split/index.html
初始代码是从网上来的,不过网上的并不完整,父 div 的高也不能改变,并且孩子的宽高并不是百分比的,布局也并不合理,所以修改成这样子。
5. 最后

微信公众号:BiaoChenXuYing 分享 前端、后端开发等相关的技术文章,热点资源,随想随感,全栈程序员的成长之路。
关注公众号并回复 福利 便免费送你视频资源,绝对干货。
福利详情请点击:免费资源分享 –Python、Java、Linux、Go、node、vue、react、javaScript

正文完
 0