首页 > 解决方案 > 鼠标移动事件中 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>

标签: javascripthtmlcss

解决方案


原因是当我们上下移动时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>


推荐阅读