したいこと
Flexで並べた要素の間に境界を設置して、そこをドラッグすることでそれぞれの幅を変えられるようにする。
例えるならVSCodeの分割ウィンドウみたいな感じ。
コード
HTML
<div id="wrapper">
<div id="one"></div>
<div id="two"></div>
</div>
###CSS
#wrapper {
display: flex;
height: 200px;
width: 300px;
}
#one, #two {
height: 100%;
}
```
###JavaScript
````javascript
window.onload = () => {
let parent = document.getElementById("wrapper");
colResizeable(parent, 300);
};
let colResizeable = (element, options) => {
let {totalWidth, borderWidth, borderColor, postProcess} = {
totalWidth: element.clientWidth,
borderWidth: 10,
borderColor: "#ddd",
postProcess: () => {},
...options
}
let w1;
let p1;
// setup
let children = Array.prototype.filter.call((element.childNodes), (e) => e.nodeName != "#text");
let child1 = children[0];
let child2 = children[1];
children.forEach((e) => { e.style.width = (totalWidth - borderWidth) / 2 + "px" });
// insert border between children
let border = document.createElement("div");
let borderStyle = {
width: borderWidth + "px",
backgroundColor: borderColor,
cursor: "col-resize"
}
Object.keys(borderStyle).forEach((key) => { border.style[key] = borderStyle[key] });
element.insertBefore(border, child1.nextSibling);
let resizeChildren = (event) => {
let w2 = Math.min(Math.max(0, w1 + event.pageX - p1), totalWidth - borderWidth);
child1.style.width = w2 + "px";
child2.style.width = totalWidth - w2 - borderWidth + "px";
};
border.addEventListener("mousedown", (event) => {
w1 = Number(/.*?(?=px)/.exec(child1.style.width));
p1 = event.pageX;
element.addEventListener("mousemove", resizeChildren);
});
window.addEventListener("mouseup", () => {
element.removeEventListener("mousemove", resizeChildren)
postProcess;
});
}
##ポイント
https://qiita.com/NoSuke23/items/54df05a61568246166b4#%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88
- Array.prototype.filter.call((element.childNodes), (e) => e.nodeName != "#text")で空のテキスト要素を弾ける
- ドラッグはmousedownしたときのカーソルの座標とmousemoveのときの座標の相対値を取る
- 面積の小さい要素を動かすときはwindow.addEventListener("mouseup", func)がおすすめ