Article directory
1. Pure css3
The specific usage of the resize attribute can be found on MDN: https://developer.mozilla.org/zh-CN/docs/Web/CSS/resize
Effect link: http://js.jirengu.com/voleracixe/2/edit
Utilize the resize feature of the browser's non-overflow:auto element to achieve JavaScript-free column width control.
principle
There is a resize attribute in CSS. If the overflow attribute value of an element is not visible, the size of the element can be stretched by setting the resize attribute.
How to make the drag area larger?
Later research found that the drag bar of the resize attribute and the drag bar of the scroll bar are things in the same system. You only need to customize the scroll bar to indirectly set the size of the resize bar.
.resize-bar::-webkit-scrollbar {
width: 200px; height: 200px;
}
a complete example
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AA-drag</title>
<style>
* {
padding: 0;
margin: 0;
}
.fl-container {
width: 100%;
height: 100vh;
overflow: hidden;
}
.fl-resize-bar,
.fl-resize-bar::-webkit-scrollbar {
width: 400px;
}
.fl-left {
position: relative;
float: left;
height: 100vh;
background: pink;
}
.fl-right {
box-sizing: border-box;
overflow-x: hidden;
height: 100vh;
}
.fl-cont-right {
height: 200vh;
}
.fl-resize-bar {
height: inherit;
resize: horizontal;
cursor: ew-resize;
cursor: col-resize;
opacity: 0;
overflow: scroll;
}
.fl-resize-bar::-webkit-scrollbar {
width: 400px;
height: inherit;
}
.fl-cont-left {
position: absolute;
top: 0;
right: 4px; /* 拖拽线的间距 */
bottom: 0;
left: 0;
overflow-x: hidden;
background: #fff;
}
.fl-resize-line {
position: absolute;
right: 1px;
top: 0;
bottom: 0;
border-right: 2px solid #bbb;
pointer-events: none;
}
.fl-resize-bar:hover ~ .fl-resize-line,
.fl-resize-bar:active ~ .fl-resize-line {
border-right: 2px dashed skyblue;
}
/* Firefox只有下面一小块区域可以拉伸 */
@supports (-moz-user-select: none) {
.fl-resize-bar:hover ~ .fl-resize-line,
.fl-resize-bar:active ~ .fl-resize-line {
border-right: 2px solid #bbb;
}
.fl-resize-bar:hover ~ .fl-resize-line::after,
.fl-resize-bar:active ~ .fl-resize-line::after {
content: '';
position: absolute;
width: 16px;
height: 16px;
bottom: 0;
right: -8px;
background: url(https://www.zhangxinxu.com/study/201903/css-idea/resize.svg);
background-size: 100% 100%;
z-index: 1;
}
}
</style>
</head>
<body>
<div class="fl-container">
<div class="fl-left">
<div class="fl-resize-bar"></div>
<div class="fl-resize-line"></div>
<div class="fl-cont-left">左侧内容</div>
</div>
<div class="fl-right">
<div class="fl-cont-right">
右侧内容
</div>
</div>
</div>
</body>
</html>
2. Pure js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AA-drag</title>
<style>
* {
padding: 0;
margin: 0;
}
#left,
#right,
#middle {
height: 100vh;
position: absolute;
}
#left {
width: 300px;
background: #ccc;
}
#middle {
width: 5px;
background: #666;
left: 300px;
}
#middle:hover {
cursor: col-resize;
}
#right {
right: 0;
background: #ccc;
left: 305px;
width: auto;
}
</style>
</head>
<body>
<div id="left">左侧内容</div>
<div id="middle"></div>
<div id="right">右侧内容</div>
</body>
</html>
<script>
function getEle(id) {
return document.getElementById(id)
}
window.onload = function () {
const left = getEle('left')
const right = getEle('right')
const middle = getEle('middle')
const middleWidth = 5
middle.onmousedown = function (e) {
const disX = (e || event).clientX
middle.left = middle.offsetLeft
document.onmousemove = function (e) {
let middleLeft = middle.left + ((e || event).clientX - disX)
const maxWidth = document.body.clientWidth
middleLeft < 0 && (middleLeft = 0)
middleLeft > maxWidth && (middleLeft = maxWidth)
middle.style.left = left.style.width = `${
middleLeft}px`
right.style.width = `${
maxWidth - middleLeft - middleWidth}px`
right.style.left = `${
middleLeft + middleWidth}px`
return false
}
document.onmouseup = function () {
document.onmousemove = null
document.onmouseup = null
middle.releaseCapture && middle.releaseCapture()
}
middle.setCapture && middle.setCapture()
return false
}
}
</script>
2.1. onmousedown, onmousemove, onmouseup mouse press/move/release
1. onmousedown——select element
oDiv.onmousedown = function(ev) {
}
2. onmousemove - moving elements
Trigger frequency: not pixels, but interval time. Within a specified time (very short), if the position of the mouse changes from the previous position, it will trigger once
var i = 0;
document.onmousemove = function() {
document.title = i++; //鼠标移动,页面的标题发生变化,移动的越慢数字越大
}
3. onmouseup - release elements
document.onmouseup = function() {
}
4. Structural relationship among the three
oDiv.onmousedown = function() {
document.onmousemove = function() {
}
//拖动的太快了超出元素的本身的位置会停在半路,所以元素改为文档
document.onmouseup = function() {
}
//如果有别的元素在拖动元素停止的位置之上,松开鼠标则还可以继续拖动,因为不是在拖动元素上松开的,所以元素应改为文档
}
2.2. Attention
1. When dragging, if any text is selected, problems will occur.
Reason: When the mouse is pressed, if text is selected on the page, the browser's default dragging effect will be triggered.
Solution:
(1) Standard browser: block default behavior
return false;
(2) IE678: There is no way to prevent it, so you need to set up global capture - .setCapture()
if ( obj.setCapture ) {
obj.setCapture();
}
2.3 Switch the browser window size and recalculate the size
onMounted(() => {
window.addEventListener('resize', () => {
resizeInit()
})
})
function resizeInit() {
const left = getEle('left')
const right = getEle('right')
const middle = getEle('middle')
left.style.width = '300px'
middle.style.left = '310px'
const maxWidth = (document.body.clientWidth - 50) * 2/3
right.style.width = `${
maxWidth - 311 - 20}px`
right.style.left = '311px'
}
3. splitpanes plug-in (vertical and horizontal split windows)
Official website: https://antoniandre.github.io/splitpanes/
Use in vue3 project
Install
pnpm i splitpanes@next
Use on the page
import {
Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
html in
min-size="0" max-size="35" sets the maximum and minimum percentages that can be adjusted in the left window
<splitpanes class="default-theme" @resize="paneSize = $event[0].size" style="height: 400px">
<pane :size="paneSize" min-size="0" max-size="35">
<span>{
{
paneSize }}%</span>
</pane>
<pane :size="100 - paneSize">
<span>{
{
100 - paneSize }}%</span>
</pane>
</splitpanes>