文章目录
一、纯css3
resize属性的具体用法可见MDN: https://developer.mozilla.org/zh-CN/docs/Web/CSS/resize
效果链接: http://js.jirengu.com/voleracixe/2/edit
利用浏览器非overflow:auto元素设置resize可以拉伸的特性实现无JavaScript的分栏宽度控制。
原理
CSS中有一个resize属性,如果一个元素的overflow属性值不是visible,则通过设置resize属性可以拉伸这个元素尺寸。
如何把拖拽区域变大呢?
后来研究发现,resize属性的拖拽bar和滚动条的拖拽bar是一个体系里面的东西,只需要对滚动条进行自定义,就能间接设置resize bar的尺寸。
.resize-bar::-webkit-scrollbar {
width: 200px; height: 200px;
}
一个完整的例子
<!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>
二、纯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 鼠标按下 / 移动 / 释放
1、onmousedown——选择元素
扫描二维码关注公众号,回复:
16860119 查看本文章
oDiv.onmousedown = function(ev) {
}
2、onmousemove —— 移动元素
触发频率:不是像素,而是间隔时间,在一个指定时间内(很短),如果鼠标的位置和上一次的位置发生了变化,那么就会触发一次
var i = 0;
document.onmousemove = function() {
document.title = i++; //鼠标移动,页面的标题发生变化,移动的越慢数字越大
}
3、onmouseup —— 释放元素
document.onmouseup = function() {
}
4、三者结构关系
oDiv.onmousedown = function() {
document.onmousemove = function() {
}
//拖动的太快了超出元素的本身的位置会停在半路,所以元素改为文档
document.onmouseup = function() {
}
//如果有别的元素在拖动元素停止的位置之上,松开鼠标则还可以继续拖动,因为不是在拖动元素上松开的,所以元素应改为文档
}
2.2、注意
1、拖拽的时候,如果有文字被选中,会产生问题
原因:当鼠标按下的时候,如果页面中有文字被选中,那么会触发浏览器默认拖拽文字的效果
解决办法:
(1)标准浏览器:阻止默认行为
return false;
(2)IE678:没法阻止,所以需要设置全局捕获——.setCapture()
if ( obj.setCapture ) {
obj.setCapture();
}
2.3 切换浏览器窗口大小,重新计算大小
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'
}
三、splitpanes插件(垂直水平分割窗口)
官网:https://antoniandre.github.io/splitpanes/
在vue3项目中的使用
安装
pnpm i splitpanes@next
在页面的使用
import {
Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
html中
min-size=“0” max-size="35"设置左边窗口可调节的最大百分比和最小百分比
<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>