Flexbox调整大小 [英] Flexbox resizing

查看:77
本文介绍了Flexbox调整大小的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试提出一种有效的方法来定义嵌套的flexbox并允许其调整大小.我认为它快要出现了:

I'm trying to come up with an effective way of defining a nested flexbox and allow it to be resized. I think it's almost there:

http://jsfiddle.net/6j10L3x2/1/

我纯粹是使用三个自定义元素来使标记更具说明性:

I'm using three custom elements purely to make the mark-up more declarative:

flex, flex-item, flex-resizer

flex表示容器.一个flex-item在容器中显示一个元素,而flex-resizer表示一个resizer小部件,可以将其放置在两个flex-item之间以在它们之间添加调整大小的功能.

A flex represents the container. A flex-item presents an element within the container, and flex-resizer represents a resizer widget which can be placed between two flex-items to add resizing functionality between them.

这一切看起来都很好.但是,它仅处理使用flex-grow调整大小的项目.如果定义了flex-shrink或flex-basis,那么这些计算就根本不起作用.

This all appears to work really well. However, it only handles items sized with flex-grow. If flex-shrink or flex-basis is defined, then the calculations simply don't work.

有人可以提出一种修改此方法的方法,以使其适用于所有情况吗?我意识到在具有各种弹性配置的项目之间如何共享空间方面存在一些歧义,但是任何输入都将受到欢迎.

Can anyone suggest a way to amend this to allow it work for all cases? I realise that there is some ambiguity in regards to how the space should be shared between items with various flex configurations, but any input would be welcome.

任何替代方法也将受到欢迎.谢谢.

Any alternative approaches would be welcome also. Thanks.

推荐答案

哇.让您印象深刻的是如何使用'flexGrow',出色的构想和代码通过香草javascript调整flexbox元素的大小.

Wow. I am impressed how you resize the flexbox elements with vanilla javascript using 'flexGrow', excelent idea and code.

我已经通过几种方式改进了您的代码,并且效果很好.

I have improve your code in a few ways and it is working very well.

我做了什么?

1.-我简化了HTML:

1.- I simplified the HTML:

  • 请勿在 flex项目中使用 flex 元素.

始终在另一个内部使用 flex flex-item 元素. flex 元素.

Use a flex or flex-item element, always!, inside another flex element.

2.-解决了! 可见的flex-item大小小于其内容大小时,拆分器的跳转.

2.- Solved! Splitter's jump when the visible flex-item size is smaller that its content size.

3.-我添加了不同的游标以表示状态的更改(setupResizerEvents,onMouseUp)以提高可用性.

3.- I'd added different cursors to signal a state's change (setupResizerEvents, onMouseUp) to improve usability.

4.-我添加了代码,以防止拖动时光标闪烁.

4.- I've added code to prevent the cursor from flickering when dragging.

5.-在manageResize()和scrollWidth和scrollHeight中使用offsetWidth和offsetHeight来避免弹性项目内容溢出(溢出:自动)时拆分器在调整大小时跳转.

5.- use of offsetWidth and offsetHeight in manageResize() versus scrollWidth and scrollHeight to avoid splitter's jump on resize when a flex-item content overflow (overflow: auto).

这是代码:

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上看到它:

Or see it on Codesandbox:

希望对您有帮助!

这篇关于Flexbox调整大小的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆