javascript - 鼠标移动事件中 div 大小和位置更新的问题
问题描述
我正在使用 html、css 和 javascript 实现一个简单的水平拆分窗格,改编自这篇文章。
虽然对于垂直拆分窗格来说一切都很顺利,但水平实现是生涩的。div 的大小和位置跳到一个意外的值,但我无法确定何时。
这个问题在下面的代码片段中非常微妙,但可以观察到一些跳跃和滞后。
片段如下:
function dragElement(element, direction) {
var md;
const first = document.getElementById("map");
const second = document.getElementById("table");
element.onmousedown = onMouseDown;
function onMouseDown(e) {
md = {
e,
offsetLeft: element.offsetLeft,
offsetTop: element.offsetTop,
offsetBottom: element.offsetBottom,
firstWidth: first.offsetWidth,
secondWidth: second.offsetWidth,
firstHeight: first.offsetHeight,
secondHeight: first.offsetHeight
};
document.onmousemove = onMouseMove;
document.onmouseup = () => {
document.onmousemove = document.onmouseup = null;
}
}
function onMouseMove(e) {
var delta = {
x: e.clientX - md.e.x,
y: e.clientY - md.e.y
};
if (direction === "H") {
delta.x = Math.min(Math.max(delta.x, - md.firstWidth),
md.secondWidth);
element.style.left = md.offsetLeft + delta.x + "px";
first.style.width = (md.firstWidth + delta.x) + "px";
second.style.width = (md.secondWidth - delta.x) + "px";
}
if (direction === "V") {
delta.y = Math.min(Math.max(delta.y, - md.firstHeight), md.secondHeight);
element.style.top = md.offsetTop + delta.y + "px";
first.style.height = (md.firstHeight + delta.y) + "px";
second.style.height = (md.secondHeight - delta.y) + "px";
}
}
}
dragElement(document.getElementById("separator"), "V");
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.splitter {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
/*for horizontal*/
#separator {
cursor: row-resize;
background-color: #aaa;
background-repeat: no-repeat;
background-position: center;
width: 100%;
height: 10px;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#map {
width: 100%;
height: 20%;
min-height: 10px;
padding: 0;
margin: 0;
}
#table {
width: 100%;
height: 20%;
min-height: 10px;
}
<div class="splitter">
<div id="map"></div>
<div id="separator"></div>
<div id="table"></div>
</div>
解决方案
原因是当我们上下移动时secondHeight为 0。所以我得到拆分器类的高度并减去 firstHeight 形式,并且值等于 secondHeight。
secondHeight: (splitter.offsetHeight - first.offsetHeight)
function dragElement(element, direction) {
var md;
const first = document.getElementById("map");
const second = document.getElementById("table");
const splitter = document.getElementById("container");
element.onmousedown = onMouseDown;
function onMouseDown(e) {
md = {
e,
offsetLeft: element.offsetLeft,
offsetTop: element.offsetTop,
offsetBottom: element.offsetBottom,
firstWidth: first.offsetWidth,
secondWidth: second.offsetWidth,
firstHeight: first.offsetHeight,
secondHeight: (splitter.offsetHeight - first.offsetHeight)
};
document.onmousemove = onMouseMove;
document.onmouseup = () => {
document.onmousemove = document.onmouseup = null;
}
}
function onMouseMove(e) {
var delta = {
x: e.clientX - md.e.x,
y: e.clientY - md.e.y
};
if (direction === "H") {
delta.x = Math.min(Math.max(delta.x, -md.firstWidth),
md.secondWidth);
element.style.left = md.offsetLeft + delta.x + "px";
first.style.width = (md.firstWidth + delta.x) + "px";
second.style.width = (md.secondWidth - delta.x) + "px";
}
if (direction === "V") {
delta.y = Math.min(Math.max(delta.y, -md.firstHeight), md.secondHeight);
element.style.top = md.offsetTop + delta.y + "px";
first.style.height = (md.firstHeight + delta.y) + "px";
second.style.height = (md.secondHeight - delta.y) + "px";
}
}
}
dragElement(document.getElementById("separator"), "V");
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
.splitter {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
/*for horizontal*/
#separator {
cursor: row-resize;
background-color: #aaa;
background-repeat: no-repeat;
background-position: center;
width: 100%;
height: 10px;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
#map {
width: 100%;
height: 20%;
min-height: 10px;
padding: 0;
margin: 0;
}
#table {
width: 100%;
height: 20%;
min-height: 10px;
}
<div id="container" class="splitter">
<div id="map"></div>
<div id="separator"></div>
<div id="table"></div>
</div>
推荐阅读
- javascript - Vue.js - JSON API 数据不会出现在点击事件上
- python - 如何将 `__class__.__name__` 设置为类属性?
- javascript - 在数组javascript中组合(加入)对象
- typescript - 模拟函数时类型 X 上不存在属性 X
- javascript - 使用 VueCLI 找不到 this.array.ForEach 依赖项
- javascript - 显示其他图像时图像从页面中消失
- python - 正则前瞻和后瞻正则表达式模式
- c - Valgrind + C:无错误地处理未初始化的指针
- sql - SQL 统计连续获胜的用户
- r - R中的循环+环境:将新变量名分配给列值