有没有人知道在html中制作可调整大小的拆分窗格的好方法?
可以使用css / jquery / javascript来完成,还是有人知道他们使用过的好的javascript库?
(拆分窗格的一个示例是Internet Explorer中的收藏夹栏,您可能已将其停靠在主浏览器窗口的左侧)
答案 0 :(得分:77)
我想要一个vanilla,轻量级(jQuery UI Layout的重量为185kb),没有依赖选项(所有现有的库都需要jQuery)所以我写了Split.js。
它的重量小于2kb,不需要任何特殊标记。它支持旧版浏览器返回IE9(或带有polyfill的IE8)。对于现代浏览器,您可以将其与Flexbox和网格布局一起使用。
答案 1 :(得分:36)
肯定已经有很多实现了。继承人之一:http://layout.jquery-dev.com/在此处演示:http://layout.jquery-dev.com/demos/simple.html此处的源代码:https://github.com/allpro/layout/
答案 2 :(得分:11)
这是我的轻量级vanilla js方法,使用flexbox:
http://codepen.io/lingtalfi/pen/zoNeJp
在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 js轻量级库(少于60行代码)。
答案 3 :(得分:6)
在过去,你会使用框架来实现这一目标。这种方法不太好的原因有几个。请参阅Reece对why frames are bad的回复。另见Jakob Nielson的 Why Frames Suck (Most of the Time)
更新的方法是使用内联框架。这也有优点和缺点:Are iframes considered 'bad practice'?
更好的方法是使用固定定位。通过将导航内容(例如示例中的收藏夹链接)放在块元素(如div
)中,然后将position:fixed
应用于该元素并设置左,上,下属性,如下所示: / p>
#myNav {
position:fixed;
left:0px;
top:0px;
bottom:0px;
width:200px;
}
...您将在页面左侧实现一个垂直列,当用户滚动页面时,该列不会移动。
页面上的其他内容不会“感觉到”此nav元素的存在,因此它必须考虑它占用的200px空间。您可以通过将内容的其余部分放在另一个div中并设置margin-left:200px;
。
答案 4 :(得分:4)
我为它编写了一个简单的代码,没有任何第三方库;此代码仅适用于水平分离器(垂直相同)
function onload()
{
dragElement( document.getElementById("seperator"), "H" );
}
// 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 );
// 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; }
}
// 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;
}
#seperator {
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="seperator"></div>
<div id="second"></div>
</div>
</body>
</html>
答案 5 :(得分:3)
一种完全不同的方法是将事物放在网格中,例如ui-grid或Kendo的网格,并使列可以调整大小。缺点是用户无法调整行的大小,尽管行大小可以通过编程方式设置。
答案 6 :(得分:3)
嗯,我在CSS3中遇到过这个属性。 这可能更容易使用。 https://www.w3schools.com/cssref/css3_pr_resize.asp
答案 7 :(得分: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;
}
答案 8 :(得分:2)
你可以在没有其他JS库的情况下使用JqueryUI。只需向.resizable
resize事件添加一个函数即可调整另一个div的宽度。
$("#left_pane").resizable({
handles: 'e', // 'East' side of div draggable
resize: function() {
$("#right_pane").outerWidth( $("#container").innerWidth() - $("#left_pane").outerWidth() );
}
});
这是完整的JS Fiddle。
答案 9 :(得分:1)
我找到了与jquery v1.9
一起使用的工作拆分器http://www.dreamchain.com/split-pane/。注意我必须添加以下CSS代码才能使用固定的bootstrap
导航栏。
fixed-left {
position: absolute !important; /* to override relative */
height: auto !important;
top: 55px; /* fixed navbar height */
bottom: 0px;
}
答案 10 :(得分:1)
最简单的手风琴,仅需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>
Hello world!
</div>
<div>
Hello world!
</div>
<div>
Hello world!
</div>
</div>
最简单的垂直可调整大小窗格:
div {
resize: horizontal;
overflow: auto;
border: 1px solid;
display: inline-flex;
height:90vh
}
<div>
Hello world!
</div>
<div>
Hello world!
</div>
答案 11 :(得分:1)
改善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 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>
// 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.x,
y: e.clientY - md.e.y};
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>
答案 12 :(得分:1)
没有3d派对库的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>
答案 13 :(得分:0)
一个好的库是Shield UI - 您可以查看它们灵活的Splitter widget以及框架提供的其他强大组件。
答案 14 :(得分:-1)
许多人错过了 Barguast 在15年2月27日发布的这篇文章,其中展示了一个有趣的通用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>