Flexbox调整大小

时间:2015-02-27 14:19:44

标签: html html5 flexbox

我正在尝试提出一种定义嵌套Flexbox的有效方法,并允许调整它的大小。我认为它几乎就在那里:

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

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

flex, flex-item, flex-resizer

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

这一切似乎都很有效。但是,它只处理使用flex-grow大小调整的项目。如果定义了flex-shrink或flex-basis,那么计算就不起作用了。

有人可以建议一种方法来修改它以使其适用于所有情况吗?我意识到在如何在具有各种弹性配置的项目之间共享空间方面存在一些模糊性,但任何输入都是受欢迎的。

也欢迎任何替代方法。感谢。

2 个答案:

答案 0 :(得分:1)

注意:还有一个新的基本resize CSS属性,但仅用于右下角拖动。


我对此进行了一些研究,然后我发现的前三个无框架,完全烘焙的结果是按出现的顺序(未经测试):

  1. https://daybrush.com/moveable

    • “可移动,可拖动,可调整大小,可缩放,可旋转,可变形,可捏,可分组,可卡住”
    • 在视觉和代码方面,我都喜欢这里的外观!似乎功能强大且非常灵活。
    • 另请参见:https://github.com/daybrush/moveable https://daybrush.com/moveable/release/latest/doc
    • 更新:我尝试了此操作,但实际上我不建议这样做。它的使用非常复杂,文档记录不多,我宁愿自己编写JS。
  2. https://split.js.org

  3. https://jspanel.de

我还发现了这一点:http://w2ui.com/web/home https://github.com/vitmalina/w2ui

答案 1 :(得分:0)

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

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

我做了什么?

1.-我简化了HTML:

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

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

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

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

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

代码如下:

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 clientWidth versus scrollWidth to avoid splitter's jump on resize.
			manageResize(md, "clientWidth", "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, "clientHeight", "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;
}

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;">Flex 2</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上看到它:

Edit sad-butterfly-1fwo4

希望对您有帮助!