需求效果
代码实现
html&css
<template>
<div id="app">
<!-- 左 -->
<div class="left">
<div class="left-top" />
<!-- 左上 -->
<div class="resizeBar h" ref="resizeTopBar" />
<!-- 左下 -->
<div class="left-bottom" />
</div>
<div class="resizeBar v" ref="resizeLeftBar" />
<!-- 中 -->
<div class="medium" />
<!-- 右 -->
<div class="resizeBar v" ref="resizeRightBar" />
<div class="right" />
</div>
</template>
<style>
body,
html,
#app {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
#app {
display: flex;
}
.left {
flex: 0 0 200px;
display: flex;
flex-direction: column;
}
.left-top {
flex: 0 0 50%;
background-color: lightsteelblue;
}
.left-bottom {
flex: 1;
background-color: burlywood;
}
.medium {
flex: 1
}
.right {
flex: 0 0 200px;
background-color: bisque;
}
.resizeBar {
background-color: #000;
}
.resizeBar.v {
width: 5px;
height: 100%;
}
.resizeBar.h {
width: 100%;
height: 5px;
}
.resizeBar.v:hover {
cursor: col-resize
}
.resizeBar.h:hover {
cursor: row-resize
}
</style>
js
<script>
export default {
name: 'App',
mounted() {
this.resizeTopAndBottom()
this.resizeLeftAndMedium()
this.resizeRightAndMedium()
},
methods: {
// 左上-左下之间的拖动,改变左上的高度,左下设置flex:1;高度自适应
resizeTopAndBottom() {
const resizeElement = document.querySelector('.left-top')
this.$refs['resizeTopBar'].onmousedown = e => {
// left-top初始高度
const oldHeight = resizeElement.offsetHeight
// 点击鼠标初始Y值
const startY = e.clientY
document.onmousemove = e => {
// 当前鼠标Y值
const endY = e.clientY
// 当前鼠标在Y轴移动的距离
const distance = endY - startY
// left-top当前高度
const newHeight = oldHeight + distance
// 设置dom样式
resizeElement.style.flex = `0 0 ${newHeight}px`
}
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
}
return false
}
},
// 左-中之间的拖动,改变左的宽度,中设置flex:1;宽度自适应
resizeLeftAndMedium() {
const resizeElement = document.querySelector('.left')
this.$refs['resizeLeftBar'].onmousedown = e => {
// left初始宽度
const oldWidth = resizeElement.offsetWidth
// 点击鼠标初始X值
const startX = e.clientX
document.onmousemove = e => {
// 当前鼠标X值
const endX = e.clientX
// 当前鼠标在X轴移动的距离
const distance = endX - startX
// left-top当前高度
const newWidth = oldWidth + distance
// 设置dom样式
resizeElement.style.flex = `0 0 ${newWidth}px`
}
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
}
return false
}
},
// 中-右之间的拖动,改变右的宽度,中设置flex:1;宽度自适应
resizeRightAndMedium() {
const resizeElement = document.querySelector('.right')
this.$refs['resizeRightBar'].onmousedown = e => {
// left初始宽度
const oldWidth = resizeElement.offsetWidth
// 点击鼠标初始X值
const startX = e.clientX
document.onmousemove = e => {
// 当前鼠标X值
const endX = e.clientX
// 当前鼠标在X轴移动的距离
const distance = startX - endX
// left-top当前高度
const newWidth = oldWidth + distance
// 设置dom样式
resizeElement.style.flex = `0 0 ${newWidth}px`
}
document.onmouseup = () => {
document.onmousemove = null;
document.onmouseup = null;
}
return false
}
}
}
}
</script>
思路
以 左-中-右 三列布局为例
- 样式上,采用flex布局比较便捷,左右给一个初始的固定宽,中就flex:1;,这样左右宽度改变中也能自适应改变宽度
- 在左-中,中-右,之间添加一个元素作为拖动的抓手,通过拖动抓手来改变布局元素的宽高
- 拖动抓手
- 抓手onmousedown事件,获取鼠标点击时的初始X值或Y值,以及要改变宽高元素的初始宽高
- document onmousemove事件,通过鼠标移动,实时获取当前鼠标X或Y值,计算鼠标实时的水平/垂直移动距离,计算元素的实时宽高,并设置样式
- document onmouseup,鼠标抬起,拖动结束,清空事件