78

有没有一种很好的技术可以在 HTML 中制作可调整大小的拆分窗格?

是否可以使用 CSS / jQuery / JavaScript 完成,或者是否有一个好的 JavaScript 库已经使用?

(拆分窗格的一个示例是Internet Explorer中的收藏夹栏,您可能已将其停靠在主浏览器窗口的左侧。)

4

14 回答 14

103

我想要一个普通的、轻量级的(jQuery UI Layout 大小为 185 KB),没有依赖选项(所有现有的库都需要 jQuery),所以我编写了Split.js

它的重量小于 2 KB,不需要任何特殊标记。它支持旧版浏览器回到 Internet Explorer 9(或带有 polyfills 的 Internet Explorer 8)。对于现代浏览器,您可以将其与Flexbox网格布局一起使用。

于 2015-08-29T17:20:29.690 回答
33

改进Reza 的回答

  • 防止浏览器干扰拖动
  • 防止将元素设置为负大小
  • 防止由于与元素宽度饱和的增量增量交互而导致拖动与鼠标不同步

<html><head><style>

.splitter {
    width: 100%;
    height: 100px;
    display: flex;
}

#separator {
    cursor: col-resize;
    background-color: #aaa;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='30'><path d='M2 0 v30 M5 0 v30 M8 0 v30' fill='none' stroke='black'/></svg>");
    background-repeat: no-repeat;
    background-position: center;
    width: 10px;
    height: 100%;

    /* Prevent the browser's built-in drag from interfering */
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none;
}

#first {
    background-color: #dde;
    width: 20%;
    height: 100%;
    min-width: 10px;
}

#second {
    background-color: #eee;
    width: 80%;
    height: 100%;
    min-width: 10px;
}

</style></head><body>

<div class="splitter">
    <div id="first"></div>
    <div id="separator" ></div>
    <div id="second" ></div>
</div>

<script>

// A function is used for dragging and moving
function dragElement(element, direction)
{
    var   md; // remember mouse down info
    const first  = document.getElementById("first");
    const second = document.getElementById("second");

    element.onmousedown = onMouseDown;

    function onMouseDown(e)
    {
        //console.log("mouse down: " + e.clientX);
        md = {e,
              offsetLeft:  element.offsetLeft,
              offsetTop:   element.offsetTop,
              firstWidth:  first.offsetWidth,
              secondWidth: second.offsetWidth
             };

        document.onmousemove = onMouseMove;
        document.onmouseup = () => {
            //console.log("mouse up");
            document.onmousemove = document.onmouseup = null;
        }
    }

    function onMouseMove(e)
    {
        //console.log("mouse move: " + e.clientX);
        var delta = {x: e.clientX - md.e.clientX,
                     y: e.clientY - md.e.clientY};

        if (direction === "H" ) // Horizontal
        {
            // Prevent negative-sized elements
            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";
        }
    }
}


dragElement( document.getElementById("separator"), "H" );

</script></body></html>

于 2019-03-17T00:10:01.667 回答
28

最简单的 HTML + CSS 手风琴,只需CSS resize

div {
  resize: vertical;
  overflow: auto;
  border: 1px solid
}
.menu {
  display: grid
  /* Try height: 100% or height: 100vh */
}
<div class="menu">
  <div>
    Hello, World!
  </div>
  <div>
    Hello, World!
  </div>
  <div>
    Hello, World!
  </div>
</div>


最简单的 HTML + CSS 垂直可调整大小的窗格:

div {
  resize: horizontal;
  overflow: auto;
  border: 1px solid;
  display: inline-flex;
  height: 90vh
}
<div>
  Hello, World!
</div>
<div>
  Hello, World!
</div>


纯 HTML,详细信息元素!.

<details>
  <summary>Morning</summary>
  <p>Hello, World!</p>
</details>
<details>
  <summary>Evening</summary>
  <p>How sweat?</p>
</details>


最简单的 HTML + CSS 顶栏折叠菜单

div{
 display: flex
}
summary,p{
 margin: 0px 0 -1px 0px;
 padding: 0 0 0 0.5rem;
 border: 1px black solid
}
summary {
  padding: 0 1rem 0 0.5rem
}
<div>
  <details>
    <summary>FILE</summary>
    <p>Save</p>
    <p>Save as</p>
  </details>
  <details>
    <summary>EDIT</summary>
    <p>Pump</p>
    <p>Transfer</p>
    <p>Review</p>
    <p>Compile</p>
  </details>
  <details>
    <summary>PREFERENCES</summary>
    <p>How sweat?</p>
    <p>Powered by HTML</p>
  </details>
</div>


固定底部菜单栏,向上展开。

div{
 display: flex;
 position: fixed;
 bottom: 0;
 transform: rotate(180deg)
}
summary,p{
 margin: 0px 0 -1px 0px;
 padding: 0 0 0 0.5rem;
 border: 1px black solid;
 transform: rotate(180deg)
}
summary {
  padding: 0 1rem 0 0.5rem;
}
<div>
  <details>
    <summary>FILE</summary>
    <p>Save</p>
    <p>Save as</p>
  </details>
  <details>
    <summary>EDIT</summary>
    <p>Pump</p>
    <p>Transfer</p>
    <p>Review</p>
    <p>Compile</p>
  </details>
  <details>
    <summary>PREF</summary>
    <p>How?</p>
    <p>Power</p>
  </details>
</div>


最简单的可调整大小的窗格,使用 JavaScript。

let ismdwn = 0
rpanrResize.addEventListener('mousedown', mD)

function mD(event) {
  ismdwn = 1
  document.body.addEventListener('mousemove', mV)
  document.body.addEventListener('mouseup', end)
}

function mV(event) {
  if (ismdwn === 1) {
    pan1.style.flexBasis = event.clientX + "px"
  } else {
    end()
  }
}
const end = (e) => {
  ismdwn = 0
  document.body.removeEventListener('mouseup', end)
  rpanrResize.removeEventListener('mousemove', mV)
}
div {
  display: flex;
  border: 1px black solid;
  width: 100%;
  height: 200px;
}

#pan1 {
  flex-grow: 1;
  flex-shrink: 0;
  flex-basis: 50%; // initial status
}

#pan2 {
  flex-grow: 0;
  flex-shrink: 1;
  overflow-x: auto;
}

#rpanrResize {
  flex-grow: 0;
  flex-shrink: 0;
  background: #1b1b51;
  width: 0.2rem;
  cursor: col-resize;
  margin: 0 0 0 auto;
}
<div>
  <div id="pan1">MENU</div>
  <div id="rpanrResize">&nbsp;</div>
  <div id="pan2">BODY</div>
</div>

于 2019-03-15T19:54:16.187 回答
18

我为它编写了简单的代码,没有任何第三方库。此代码仅适用于水平拆分器(垂直相同)。

function onload()
{
    dragElement( document.getElementById("separator"), "H" );
}

// This function is used for dragging and moving
function dragElement( element, direction, handler )
{
  // Two variables for tracking positions of the cursor
  const drag = { x : 0, y : 0 };
  const delta = { x : 0, y : 0 };
  /* If present, the handler is where you move the DIV from
     otherwise, move the DIV from anywhere inside the DIV */
  handler ? ( handler.onmousedown = dragMouseDown ): ( element.onmousedown = dragMouseDown );

  // A function that will be called whenever the down event of the mouse is raised
  function dragMouseDown( e )
  {
    drag.x = e.clientX;
    drag.y = e.clientY;
    document.onmousemove = onMouseMove;
    document.onmouseup = () => { document.onmousemove = document.onmouseup = null; }
  }

  // A function that will be called whenever the up event of the mouse is raised
  function onMouseMove( e )
  {
    const currentX = e.clientX;
    const currentY = e.clientY;

    delta.x = currentX - drag.x;
    delta.y = currentY - drag.y;

    const offsetLeft = element.offsetLeft;
    const offsetTop = element.offsetTop;


    const first = document.getElementById("first");
    const second = document.getElementById("second");
    let firstWidth = first.offsetWidth;
    let secondWidth = second.offsetWidth;
    if (direction === "H" ) // Horizontal
    {
        element.style.left = offsetLeft + delta.x + "px";
        firstWidth += delta.x;
        secondWidth -= delta.x;
    }
    drag.x = currentX;
    drag.y = currentY;
    first.style.width = firstWidth + "px";
    second.style.width = secondWidth + "px";
  }
}
.splitter {
    width: 500px;
    height: 100px;
    display: flex;
}

#separator {
    cursor: col-resize;
    background: url(https://raw.githubusercontent.com/RickStrahl/jquery-resizable/master/assets/vsizegrip.png) center center no-repeat #535353;
    width: 10px;
    height: 100px;
    min-width: 10px;
}

#first {
    background-color: green;
    width: 100px;
    height: 100px;
    min-width: 10px;
}

#second {
    background-color: red;
    width: 390px;
    height: 100px;
    min-width: 10px;
}
<html>

    <head>
        <link rel="stylesheet" href="T10-Splitter.css">
        <script src="T10-Splitter.js"></script>
    </head>

    <body onload="onload()">
        <div class="splitter">
            <div id="first"></div>
            <div id="separator"></div>
            <div id="second"></div>
        </div>
    </body>

</html>

于 2018-09-27T12:10:46.923 回答
14

这是我使用Flexbox的轻量级原生 JavaScript 方法:

http://codepen.io/lingtalfi/pen/zoNeJp

在Google Chrome 54, Firefox 50, Safari 10 测试成功,不知道其他浏览器。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.rawgit.com/lingtalfi/simpledrag/master/simpledrag.js"></script>

    <style type="text/css">

        html, body {
            height: 100%;
        }

        .panes-container {
            display: flex;
            width: 100%;
            overflow: hidden;
        }

        .left-pane {
            width: 18%;
            background: #ccc;
        }

        .panes-separator {
            width: 2%;
            background: red;
            position: relative;
            cursor: col-resize;
        }

        .right-pane {
            flex: auto;
            background: #eee;
        }

        .panes-container,
        .panes-separator,
        .left-pane,
        .right-pane {
            margin: 0;
            padding: 0;
            height: 100%;
        }

    </style>

</head>

<body>

<div class="panes-container">
    <div class="left-pane" id="left-pane">
        <p>I'm the left pane</p>
        <ul>
            <li><a href="#">Item 1</a></li>
            <li><a href="#">Item 2</a></li>
            <li><a href="#">Item 3</a></li>
        </ul>
    </div>
    <div class="panes-separator" id="panes-separator"></div>
    <div class="right-pane" id="right-pane">
        <p>And I'm the right pane</p>
        <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. A accusantium at cum cupiditate dolorum, eius eum
            eveniet facilis illum maiores molestiae necessitatibus optio possimus sequi sunt, vel voluptate. Asperiores,
            voluptate!
        </p>
    </div>
</div>


<script>


    var leftPane = document.getElementById('left-pane');
    var rightPane = document.getElementById('right-pane');
    var paneSep = document.getElementById('panes-separator');

    // The script below constrains the target to move horizontally between a left and a right virtual boundaries.
    // - the left limit is positioned at 10% of the screen width
    // - the right limit is positioned at 90% of the screen width
    var leftLimit = 10;
    var rightLimit = 90;


    paneSep.sdrag(function (el, pageX, startX, pageY, startY, fix) {

        fix.skipX = true;

        if (pageX < window.innerWidth * leftLimit / 100) {
            pageX = window.innerWidth * leftLimit / 100;
            fix.pageX = pageX;
        }
        if (pageX > window.innerWidth * rightLimit / 100) {
            pageX = window.innerWidth * rightLimit / 100;
            fix.pageX = pageX;
        }

        var cur = pageX / window.innerWidth * 100;
        if (cur < 0) {
            cur = 0;
        }
        if (cur > window.innerWidth) {
            cur = window.innerWidth;
        }


        var right = (100-cur-2);
        leftPane.style.width = cur + '%';
        rightPane.style.width = right + '%';

    }, null, 'horizontal');


</script>

</body>
</html>

此 HTML 代码依赖于simpledrag vanilla JavaScript 轻量级库(少于 60 行代码)。

于 2016-11-20T12:46:06.943 回答
8

嗯,我在 CSS 3 中遇到了这个属性。这可能更容易使用。

CSS 调整大小属性

于 2017-07-27T04:10:08.990 回答
7

在过去,您会使用框架来实现这一点。这种方法不太好有几个原因。请参阅 Reece 对为什么 HTML 框架不好?. 另请参阅 Jakob Nielson 的Why Frames Suck (Most of the Time)

一种新的方法是使用内联框架。这也有优点和缺点:iframe 是否被认为是“不好的做法”?

更好的方法是使用固定定位。通过将导航内容(例如,您的示例中的收藏夹链接)放置在块元素(如 a div)中,然后应用position:fixed到该元素并设置 left、top 和 bottom 属性,如下所示:

#myNav {
    position: fixed;
    left: 0px;
    top: 0px;
    bottom: 0px;
    width: 200px;
}

...您将在页面左侧实现垂直列,当用户滚动页面时该列不会移动。

页面上的其余内容不会“感觉到”这个 nav 元素的存在,所以它必须考虑到它占用的 200px 空间。您可以通过将内容的其余部分放在另一个 div 和设置中来做到这一点margin-left:200px;

于 2012-08-30T10:31:28.567 回答
4

您可以使用 jQuery UI 来完成,而无需其他 JavaScript 库。只需在.resizableresize 事件中添加一个函数来调整另一个 div 的宽度。

$("#left_pane").resizable({
  handles: 'e', // 'East' side of div draggable
  resize: function() {
    $("#right_pane").outerWidth( $("#container").innerWidth() - $("#left_pane").outerWidth() );
  }
});

这是完整的JSFiddle

于 2017-03-27T20:40:47.957 回答
3

一种完全不同的方法是将事物放在网格中,例如 ui-grid 或 Kendo 的网格,并让列可调整大小。一个缺点是用户将无法调整行的大小,尽管可以通过编程方式设置行大小。

于 2016-06-06T20:36:08.427 回答
3

许多人错过了Barguast于 15 年 2 月 27 日发布的这篇文章,其中展示了一个有趣的通用 flexbox 垂直和水平调整器。

看一看:Flexbox 调整大小

Barguast 注意到“......它只处理使用 flex-grow 调整大小的项目。如果定义了 flex-shrink 或 flex-basis,那么计算根本就不起作用。”,他正在寻找更好的解决方案,所以这样做我。

这是他的代码供参考:

function manageResize(md, sizeProp, posProp)
{
    var r = md.target;

    var prev = r.previousElementSibling;
    var next = r.nextElementSibling;
    if (!prev || !next) {
        return;
    }

    md.preventDefault();

    var prevSize = prev[sizeProp];
    var nextSize = next[sizeProp];
    var sumSize = prevSize + nextSize;
    var prevGrow = Number(prev.style.flexGrow);
    var nextGrow = Number(next.style.flexGrow);
    var sumGrow = prevGrow + nextGrow;
    var lastPos = md[posProp];

    function onMouseMove(mm)
    {
        var pos = mm[posProp];
        var d = pos - lastPos;
        prevSize += d;
        nextSize -= d;
        if (prevSize < 0) {
            nextSize += prevSize;
            pos -= prevSize;
            prevSize = 0;
        }
        if (nextSize < 0) {
            prevSize += nextSize;
            pos += nextSize;
            nextSize = 0;
        }

        var prevGrowNew = sumGrow * (prevSize / sumSize);
        var nextGrowNew = sumGrow * (nextSize / sumSize);

        prev.style.flexGrow = prevGrowNew;
        next.style.flexGrow = nextGrowNew;

        lastPos = pos;
    }

    function onMouseUp(mu)
    {
        window.removeEventListener("mousemove", onMouseMove);
        window.removeEventListener("mouseup", onMouseUp);
    }

    window.addEventListener("mousemove", onMouseMove);
    window.addEventListener("mouseup", onMouseUp);
}

function setupResizerEvents()
{
    document.body.addEventListener("mousedown", function (md) {
        var target = md.target;
        if (target.nodeType !== 1 || target.tagName !== "FLEX-RESIZER") {
            return;
        }
        var parent = target.parentNode;
        var h = parent.classList.contains("h");
        var v = parent.classList.contains("v");
        if (h && v) {
            return;
        } else if (h) {
            manageResize(md, "scrollWidth", "pageX");
        } else if (v) {
            manageResize(md, "scrollHeight", "pageY");
        }
    });
}

setupResizerEvents();
flex {
    display: flex;
}

flex-item > flex {
    position: absolute;
    width: 100%;
    height: 100%;
}

flex.h {
    -ms-flex-direction: row;
    flex-direction: row;
}

flex.v {
    -ms-flex-direction: column;
    flex-direction: column;
}

flex-item {
    display: flex;
    position: relative;
    overflow: hidden;
}

flex > flex-resizer {
    -ms-flex: 0 0 8px;
    flex: 0 0 8px;
    background: white;
}

flex.h > flex-resizer {
    cursor: ew-resize;
}

flex.v > flex-resizer {
    cursor: ns-resize;
}
<body>
    <flex class="v" style="height: 500px">
        <flex-item style="flex: 1; background: red">Flex 1</flex-item>
        <flex-resizer></flex-resizer>
        <flex-item style="flex: 1; background: blue">
            <flex class="h">
                <flex-item style="flex: 1">Flex 2</flex-item>
                <flex-resizer></flex-resizer>
                <flex-item style="flex: 2; background: green">
                    <flex class="v">
                        <flex-item style="flex: 1; background: pink;">Flex 3</flex-item>
                        <flex-resizer></flex-resizer>
                        <flex-item style="flex: 1">
                            <flex class="h">
                                <flex-item style="flex: 1">Flex 4</flex-item>
                                <flex-resizer></flex-resizer>
                                <flex-item style="flex: 2; background: yellow">Flex 5</flex-item>
                                <flex-item style="flex: 2; background: yellow">Flex 6</flex-item>
                            </flex>
                        </flex-item>
                    </flex>
                </flex-item>
            </flex>
        </flex-item>
    </flex>
</body>

这是我的改进版本:

function manageResize(md, sizeProp, posProp) {
    var r = md.target;

    var prev = r.previousElementSibling;
    var next = r.nextElementSibling;
    if (!prev || !next) {
        return;
    }

    md.preventDefault();

    var prevSize = prev[sizeProp];
    var nextSize = next[sizeProp];
    var sumSize = prevSize + nextSize;
    var prevGrow = Number(prev.style.flexGrow);
    var nextGrow = Number(next.style.flexGrow);
    var sumGrow = prevGrow + nextGrow;
    var lastPos = md[posProp];

    function onMouseMove(mm) {
        var pos = mm[posProp];
        var d = pos - lastPos;
        prevSize += d;
        nextSize -= d;
        if (prevSize < 0) {
            nextSize += prevSize;
            pos -= prevSize;
            prevSize = 0;
        }
        if (nextSize < 0) {
            prevSize += nextSize;
            pos += nextSize;
            nextSize = 0;
        }

        var prevGrowNew = sumGrow * (prevSize / sumSize);
        var nextGrowNew = sumGrow * (nextSize / sumSize);

        prev.style.flexGrow = prevGrowNew;
        next.style.flexGrow = nextGrowNew;

        lastPos = pos;
    }

    function onMouseUp(mu) {
        // Change cursor to signal a state's change: stop resizing.
        const html = document.querySelector('html');
        html.style.cursor = 'default';

        if (posProp === 'pageX') {
            r.style.cursor = 'ew-resize'; 
        } else {
            r.style.cursor = 'ns-resize';
        }
        
        window.removeEventListener("mousemove", onMouseMove);
        window.removeEventListener("mouseup", onMouseUp);
    }

    window.addEventListener("mousemove", onMouseMove);
    window.addEventListener("mouseup", onMouseUp);
}

function setupResizerEvents() {
    document.body.addEventListener("mousedown", function (md) {

        // Used to avoid cursor's flickering
        const html = document.querySelector('html');
        
        var target = md.target;
        if (target.nodeType !== 1 || target.tagName !== "FLEX-RESIZER") {
            return;
        }
        var parent = target.parentNode;
        var h = parent.classList.contains("h");
        var v = parent.classList.contains("v");
        if (h && v) {
            return;
        } else if (h) {
            // Change cursor to signal a state's change: begin resizing on H.
            target.style.cursor = 'col-resize';
            html.style.cursor = 'col-resize'; // avoid cursor's flickering

            // use offsetWidth versus scrollWidth (and clientWidth) to avoid splitter's jump on resize when a flex-item content overflow (overflow: auto).
            manageResize(md, "offsetWidth", "pageX");
            
        } else if (v) {
            // Change cursor to signal a state's change: begin resizing on V.
            target.style.cursor = 'row-resize';
            html.style.cursor = 'row-resize'; // avoid cursor's flickering

            manageResize(md, "offsetHeight", "pageY");
        }
    });
}

setupResizerEvents();
body {
    /* margin:0; */
    border: 10px solid #aaa;
}

flex {
    display: flex;
    overflow: hidden;
}

/* flex-item > flex {
    position: absolute;
    width: 100%;
    height: 100%;
} */

flex.h {
    flex-direction: row;
}

flex.v {
    flex-direction: column;
}

flex-item {
    /* display: flex; */
    /* position: relative; */
    /* overflow: hidden; */
    overflow: auto;
}

flex > flex-resizer {
    flex: 0 0 10px;
    /* background: white; */
    background-color: #aaa;
    background-repeat: no-repeat;
    background-position: center;
}

flex.h > flex-resizer {
    cursor: ew-resize;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='30'><path d='M2 0 v30 M5 0 v30 M8 0 v30' fill='none' stroke='black'/></svg>");
}

flex.v > flex-resizer {
    cursor: ns-resize;
    background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='30' height='10'><path d='M0 2 h30 M0 5 h30 M0 8 h30' fill='none' stroke='black'/></svg>");
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>flex-splitter</title>
    <link rel="stylesheet" href="./src/styles.css">
    <script src="./src/index.js" defer></script>
</head>

<body>
    <flex class="v" style="flex: 1; height: 500px;">
        <flex-item style="flex: 1;">Flex 1</flex-item>
        <flex-resizer></flex-resizer>
        <flex class="h" style="flex: 1;">
            <flex-item style="flex: 1; background-color: aqua;">
      
      <!-- 
        The next section is an example to test the splitter when there is content inside a flex-item
      -->
        <section>
                    <div>
                        <label for="CursorCoor" style="display: block;">showCursorCoor: </label>
                        <textarea id="CursorCoor" rows="6" cols="50" wrap="soft" readonly></textarea>
                    </div>
                
                    <br />
                
                    <div>
                        <label for="boxInfo" style="display: block;">showBoxInfo: </label>
                        <textarea id="boxInfo" rows="6" cols="50" wrap="soft" readonly></textarea>
                    </div>
                </section>
        
      </flex-item>
            <flex-resizer></flex-resizer>
            <flex class="v" style="flex: 2; ">
                <flex-item style="flex: 1; background: pink;">Flex 3</flex-item>
                <flex-resizer></flex-resizer>
                <flex class="h" style="flex: 1">
                    <flex-item style="flex: 1; background: green;">Flex 4</flex-item>
                    <flex-resizer></flex-resizer>
                    <flex-item style="flex: 2;">Flex 5</flex-item>
                    <!-- <flex-resizer></flex-resizer> -->
                    <flex-item style="flex: 3; background: darkorange;">Flex 6</flex-item>
                </flex>
            </flex>
        </flex>
    </flex>
    
</body>
</html>

或者在 Codesandbox 上查看:

编辑悲伤蝴蝶 1fwo4

于 2019-12-18T10:06:09.830 回答
2

您可以使用绝对定位的固定定位。例如,此 CSS 将停靠在页面左侧的 2em-bar:

body {
    padding-left: 2.5em;
}
body > #bar {
    position:fixed;
    top:0; left:0;
    width: 2em;
    height: 100%;
    border-right: 2px solid #55F; background: #ddd;
}

在 jsfiddle.net 上的演示

于 2012-08-30T10:23:38.473 回答
2

没有第三方库的 Angular 版本(基于personal_cloud的回答):

import { Component, Renderer2, ViewChild, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})

export class AppComponent implements AfterViewInit, OnDestroy {

  @ViewChild('leftPanel', {static: true})
  leftPanelElement: ElementRef;

  @ViewChild('rightPanel', {static: true})
  rightPanelElement: ElementRef;

  @ViewChild('separator', {static: true})
  separatorElement: ElementRef;

  private separatorMouseDownFunc: Function;
  private documentMouseMoveFunc: Function;
  private documentMouseUpFunc: Function;
  private documentSelectStartFunc: Function;

  private mouseDownInfo: any;

  constructor(private renderer: Renderer2) {
  }

  ngAfterViewInit() {

    // Init page separator
    this.separatorMouseDownFunc = this.renderer.listen(this.separatorElement.nativeElement, 'mousedown', e => {

      this.mouseDownInfo = {
        e: e,
        offsetLeft: this.separatorElement.nativeElement.offsetLeft,
        leftWidth: this.leftPanelElement.nativeElement.offsetWidth,
        rightWidth: this.rightPanelElement.nativeElement.offsetWidth
      };

      this.documentMouseMoveFunc = this.renderer.listen('document', 'mousemove', e => {
        let deltaX = e.clientX - this.mouseDownInfo.e.x;
        // set min and max width for left panel here
        const minLeftSize = 30;
        const maxLeftSize =  (this.mouseDownInfo.leftWidth + this.mouseDownInfo.rightWidth + 5) - 30;

        deltaX = Math.min(Math.max(deltaX, minLeftSize - this.mouseDownInfo.leftWidth), maxLeftSize - this.mouseDownInfo.leftWidth);

        this.leftPanelElement.nativeElement.style.width = this.mouseDownInfo.leftWidth + deltaX + 'px';
      });

      this.documentSelectStartFunc = this.renderer.listen('document', 'selectstart', e => {
        e.preventDefault();
      });

      this.documentMouseUpFunc = this.renderer.listen('document', 'mouseup', e => {
        this.documentMouseMoveFunc();
        this.documentSelectStartFunc();
        this.documentMouseUpFunc();
      });
    });
  }

  ngOnDestroy() {
    if (this.separatorMouseDownFunc) {
      this.separatorMouseDownFunc();
    }

    if (this.documentMouseMoveFunc) {
      this.documentMouseMoveFunc();
    }

    if (this.documentMouseUpFunc) {
      this.documentMouseUpFunc();
    }

    if (this.documentSelectStartFunc()) {
      this.documentSelectStartFunc();
    }
  }
}
.main {
  display: flex;
  height: 400px;
}

.left {
  width: calc(50% - 5px);
  background-color: rgba(0, 0, 0, 0.1);
}

.right {
  flex: auto;
  background-color: rgba(0, 0, 0, 0.2);
}

.separator {
  width: 5px;
  background-color: red;
  cursor: col-resize;
}
<div class="main">
  <div class="left" #leftPanel></div>
  <div class="separator" #separator></div>
  <div class="right" #rightPanel></div>
</div>

在 Stackblitz 上运行示例

于 2019-10-25T09:52:15.450 回答
1

我找到了一个工作拆分器http://www.dreamchain.com/split-pane/,它适用于 jQuery v1.9。请注意,我必须添加以下 CSS 代码才能使其与固定bootstrap导航栏一起使用。

fixed-left {
    position: absolute !important; /* to override relative */
    height: auto !important;
    top: 55px; /* Fixed navbar height */
    bottom: 0px;
}
于 2015-02-03T08:31:24.743 回答
0

一个很好的库是 Shield UI - 你可以看看他们灵活的Splitter 小部件和框架提供的其他强大组件。

于 2016-10-31T16:19:43.087 回答