實現可拖拽側邊欄
- 2022 年 10 月 4 日
- 筆記
- HTML, javascript, Web 前端實戰, Web 應用開發
效果演示圖
可拖拽側邊欄的使用情況非常多啊,部落格園後台管理左側邊欄就可以拖拽喲!廢話不多說,本隨筆實現的可拖拽側邊欄效果演示圖如下:
HTML 程式碼
<div class="container">
<div class="left">
<div class="resize-bar"></div>
</div>
<div class="right">
<div class="resize-bar"></div>
</div>
</div>
CSS 程式碼
html,
body {
display: flex;
justify-content: center;
align-items: center;
align-content: center;
padding: 0 !important;
margin: 0 !important;
}
.container {
width: 80vw;
height: 100vh;
display: flex;
justify-content: space-between;
align-items: center;
align-content: center;
}
.left {
position: relative;
width: 100px;
height: 100%;
background-color: rgb(160, 212, 233);
}
.left .resize-bar {
position: absolute;
top: 0;
left: 100px;
width: 3px;
height: 100%;
opacity: 0;
}
.left .resize-bar:hover {
cursor: col-resize;
opacity: 1;
background-color: rgb(210, 85, 50);
}
.right {
position: relative;
width: 100px;
height: 100%;
background-color: rgb(36, 107, 214);
}
.right .resize-bar {
position: absolute;
top: 0;
right: 100px;
width: 3px;
height: 100%;
opacity: 0;
}
.right .resize-bar:hover {
cursor: col-resize;
opacity: 1;
background-color: rgb(211, 36, 164);
}
JS 程式碼
拖拽右側邊欄
如上圖,紅色方框是 container 的區域,我們的側邊欄可移動範圍也是在 container 移動範圍內。
滑鼠按住不放拖拽右側邊欄,右側邊欄的寬度此時是逐漸增大的趨勢。滑鼠移動多少 px 根據用戶移動滑鼠的速率決定。假如,滑鼠移動到 1200px 的位置,右側邊欄左邊緣往左移動 startWidth 個像素點的距離。那麼,startWidth 該怎麼計算呢?
初始階段,右側邊欄邊緣(startWidth)應該是整個 container 的寬度減去右側邊欄的寬度。假如,container 的寬度是 1355 px,右側邊欄的寬度是 100 px;那麼,startWidth = 1355px – 100px = 1255px。此時的滑鼠移動到 1200px,那麼右側邊欄應該從邊緣部分起移動 1255px – 1200px = 55px 的距離。也就是說,原來的右側邊欄寬度 100px 應該變成 100px + 55px = 155px。
const container = document.querySelector(".container");
const right = document.querySelector(".right");
const rightResizeBar = document.querySelector(".right .resize-bar");
function moveRightBar(event) {
setTimeout(() => {
let startWidth = container.clientWidth - right.clientWidth;
let shiftWidth = startWidth - event.pageX + container.offsetLeft + right.clientWidth;
right.style.width = shiftWidth + "px";
rightResizeBar.style.right = shiftWidth + "px";
}, 200);
}
這裡要特別聲明,pageX、clientX 都是一樣的數值,用哪個都可以。而且,程式碼中還加了一個 container.offsetLeft。因為我們的 container 可能是被 flex 布局設置了居中,那麼此時 container 與瀏覽器窗口有一個 left 偏移量,所以需要加上這個 left 以保證移動距離的準確性。如效果演示圖中,container 並沒有緊挨著瀏覽器窗口的左邊邊緣處。
添加監聽器
滑鼠點擊到 rightResizeBar 元素時,就應該開啟整個 container 的 mousemove 事件:
// 1. 滑鼠按下 rightResizeBar 元素,開啟 container 的事件監聽
rightResizeBar.addEventListener("mousedown", () => {
container.addEventListener("mousemove", moveRightBar);
});
// 2. 當滑鼠從 rightResizeBar 放下時,取消監聽
rightResizeBar.addEventListener("mouseup", () => {
container.removeEventListener("mousemove", moveRightBar);
});
// 3. 當滑鼠從 container 範圍內放下時,取消監聽
container.addEventListener("mouseup", () => {
container.removeEventListener("mousemove", moveRightBar);
});
滑鼠放下時,清除事件監聽。上面的程式碼中 rightResizeBar 元素和 container 都清除了 container 的 mousemove 事件,這是為了確保清除乾淨才這樣做的。
拖拽左側邊欄
左側邊欄就非常簡單了,因為滑鼠的移動與瀏覽器的 x、y 有關係,所以,左側邊欄的右邊緣處移動正符合上面右側邊欄那樣的 startWidth,而且不需要計算。但是,必須要加上 container 的 left 偏移量,同上。
function moveLeftBar(event) {
setTimeout(() => {
let shiftWidth = event.pageX - container.offsetLeft;
left.style.width = shiftWidth + "px";
leftResizeBar.style.left = shiftWidth + "px";
}, 200);
}
添加事件監聽
leftResizeBar.addEventListener("mousedown", () => {
container.addEventListener("mousemove", moveLeftBar);
});
leftResizeBar.addEventListener("mouseup", () => {
container.removeEventListener("mousemove", moveLeftBar);
});
container.addEventListener("mouseup", () => {
container.removeEventListener("mousemove", moveLeftBar);
});