我无法使用鼠标拖动面板来调整其大小。我认为这是一个类似于 Stackoverlow 上的 this Question 的问题,因此可以用
flexbox
解决,但通过分析和测试代码,我意识到它们不是适合我的情况的正确解决方案,因为我的情况不同。 Flexbox 和这个问题似乎不是解决方案。也许这是一个涉及 Javascript 而不是 CSS 的问题。
我想要什么?我希望能够拖动右侧面板的线(图中所示的线)并调整面板大小,将其向右或向左移动。右侧面板内有一个
iframe
。如果我只将 widht:100%
设置为 iframe(在 id #preview
的 css 中),那么它的调整大小工作正常,但是当我也将 height:100%
应用于 iframe
时,它不再工作,调整大小停止。我实际上需要 iframe
也有 height:100%
因为我希望 iframe 延伸到整个面板一样长。
问题何时出现? 如果拖动右侧面板线(图中所示的线)并将其从右向左移动,则面板会正确展开。随后,在放大面板后,如果您尝试缩小它(从右向左拖动线条)并将其恢复到初始大小,那么一切都会冻结。
解决方案尝试。我尝试了各种(无用的)CSS解决方案,我也尝试使用
flexbox
,我还尝试了我在这个链接上面讨论的Stackoverflow问题的解决方案,但它都是无用的。问题似乎不是Flexbox。 Flexbox 看起来没什么用。所以我想问题可能是我用来调整大小的Javascript代码。我补充一下:建议“拖动事件”的好心用户的评论很有趣。我尝试过,但不起作用(也许是我的错误,我不知道)
P.S:我想继续使用纯JavaScript,我不想使用jQuery。另外我想使用 height:100% 和百分比而不是 height: 将 iframe 扩展到容器:? px 使用 px 请问你们有人能帮我吗?谢谢你
const gutters = document.querySelectorAll(".gutter");
const panes = document.querySelectorAll(".pane");
const minWidth = document.querySelector(".wrapper").style.getPropertyValue("--min-width");
const minHeight = document.querySelector(".wrapper").style.getPropertyValue("--min-height");
function resizer(e) {
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
// check gutter if vertical or horizontal
const is_vertical = e.currentTarget.classList.contains("gutter-v");
// get previous position (x or y depending on is_vertical)
const prev = is_vertical ? e.x : e.y;
// get current pane, the parent pane of the gutter you are moving
const currentPane = e.currentTarget.parentNode;
const currentPanel = currentPane.getBoundingClientRect();
// get previous pane, when move gutter-v:
// if current pane is center, prev pane will be left pane
// if current pane is right, prev pane will be center pane
// left pane will never be current pane cause it don't have gutter
const prevPane = currentPane.previousElementSibling;
const prevPanel = prevPane.getBoundingClientRect();
function mousemove(e) {
// minWidth and minHeight are string ('200px' and '100px' in this case), change them to integer
const min = parseInt(is_vertical ? minWidth : minHeight);
// calculate distance between prev and current position
const distance = prev - (is_vertical ? e.x : e.y);
// calculate new width/height of current pane and prev pane
const newCurrentSize = (is_vertical ? currentPanel.width : currentPanel.height) + distance;
const newPrevSize = (is_vertical ? prevPanel.width : prevPanel.height) - distance;
// if new width/height is less than min, return and don't change pane style
if (newCurrentSize < min || newPrevSize < min) return;
// change pane width/height depending on is_vertical
if (is_vertical) {
currentPane.style.width = newCurrentSize + "px";
prevPane.style.width = newPrevSize + "px";
} else {
currentPane.style.height = newCurrentSize + "px";
prevPane.style.height = newPrevSize + "px";
}
}
function mouseup() {
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
}
}
gutters.forEach((gutter) => gutter.addEventListener("mousedown", resizer));
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
}
.wrapper {
height: 100vh;
width: 100vw;
background: #333;
border: 6px solid #666;
display: flex;
}
.pane {
position: relative;
color: #fff;
/*
--min-width in .wrapper inline style
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
*/
min-width: var(--min-width);
}
.pane:last-child {
flex-grow: 1;
}
.pane:has(.pane) {
padding: 0;
display: flex;
flex-direction: column;
}
.pane>.pane {
/*
--min-height in .wrapper inline style
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
*/
min-height: var(--min-height);
}
.gutter {
--l: 100%;
--s: 10px;
background: #666;
position: absolute;
z-index: 1;
top: 0;
left: 0;
}
.gutter-v {
width: var(--s);
height: var(--l);
cursor: col-resize;
}
.gutter-h {
height: var(--s);
width: var(--l);
cursor: row-resize;
}
.left {
width: 600px;
}
.center_container {
width: 650px;
}
.center1 {
height: 700px;
}
#preview {
display: block;
width: 100%;
height: 100%;
background: #991717;
border: 0;
}
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
<div class="pane left">
This is the left pane.
</div>
<div class="pane center_container">
<div class="gutter gutter-v"></div>
<div class="pane center1">
This is the center pane1
</div>
<div class="pane">
<div class="gutter gutter-h"></div>
This is the center pane2.
</div>
</div>
<div class="pane">
<div class="gutter gutter-v"></div>
<iframe id="preview"></iframe>
</div>
</div>
iframe
是另一个页面,当鼠标放在
iframe
上时,mousemove
事件被中断。您可以添加 pointer-events: none;
来防止此问题。
#preview.resizing {
pointer-events: none;
}
然后通过js移动开始和结束时添加/删除
.resize
。
const iframes = document.querySelectorAll("iframe");
...
// in resizer()
iframes.forEach((iframe) => iframe.classList.add("resizing"));
// in mouseup()
iframes.forEach((iframe) => iframe.classList.remove("resizing"));
const gutters = document.querySelectorAll(".gutter");
const panes = document.querySelectorAll(".pane");
const minWidth = document.querySelector(".wrapper").style.getPropertyValue("--min-width");
const minHeight = document.querySelector(".wrapper").style.getPropertyValue("--min-height");
const iframes = document.querySelectorAll("iframe");
function resizer(e) {
window.addEventListener("mousemove", mousemove);
window.addEventListener("mouseup", mouseup);
// add .resizing when mousedown
iframes.forEach((iframe) => iframe.classList.add("resizing"));
// check gutter if vertical or horizontal
const is_vertical = e.currentTarget.classList.contains("gutter-v");
// get previous position (x or y depending on is_vertical)
const prev = is_vertical ? e.x : e.y;
// get current pane, the parent pane of the gutter you are moving
const currentPane = e.currentTarget.parentNode;
const currentPanel = currentPane.getBoundingClientRect();
// get previous pane, when move gutter-v:
// if current pane is center, prev pane will be left pane
// if current pane is right, prev pane will be center pane
// left pane will never be current pane cause it don't have gutter
const prevPane = currentPane.previousElementSibling;
const prevPanel = prevPane.getBoundingClientRect();
function mousemove(e) {
// minWidth and minHeight are string ('200px' and '100px' in this case), change them to integer
const min = parseInt(is_vertical ? minWidth : minHeight);
// calculate distance between prev and current position
const distance = prev - (is_vertical ? e.x : e.y);
// calculate new width/height of current pane and prev pane
const newCurrentSize = (is_vertical ? currentPanel.width : currentPanel.height) + distance;
const newPrevSize = (is_vertical ? prevPanel.width : prevPanel.height) - distance;
// if new width/height is less than min, return and don't change pane style
if (newCurrentSize < min || newPrevSize < min) return;
// change pane width/height depending on is_vertical
if (is_vertical) {
currentPane.style.width = newCurrentSize + "px";
prevPane.style.width = newPrevSize + "px";
} else {
currentPane.style.height = newCurrentSize + "px";
prevPane.style.height = newPrevSize + "px";
}
}
function mouseup() {
// remove .resizing when mouseup
iframes.forEach((iframe) => iframe.classList.remove("resizing"));
window.removeEventListener("mousemove", mousemove);
window.removeEventListener("mouseup", mouseup);
}
}
gutters.forEach((gutter) => gutter.addEventListener("mousedown", resizer));
*,
*::before,
*::after {
box-sizing: border-box;
}
body {
margin: 0;
}
.wrapper {
height: 100vh;
width: 100vw;
background: #333;
border: 6px solid #666;
display: flex;
}
.pane {
position: relative;
color: #fff;
/*
--min-width in .wrapper inline style
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
*/
min-width: var(--min-width);
}
.pane:last-child {
flex-grow: 1;
}
.pane:has(.pane) {
padding: 0;
display: flex;
flex-direction: column;
}
.pane>.pane {
/*
--min-height in .wrapper inline style
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
*/
min-height: var(--min-height);
}
.gutter {
--l: 100%;
--s: 10px;
background: #666;
position: absolute;
z-index: 1;
top: 0;
left: 0;
}
.gutter-v {
width: var(--s);
height: var(--l);
cursor: col-resize;
}
.gutter-h {
height: var(--s);
width: var(--l);
cursor: row-resize;
}
.left {
width: 600px;
}
.center_container {
width: 650px;
}
.center1 {
height: 700px;
}
#preview {
display: block;
width: 100%;
height: 100%;
background: #991717;
border: 0;
}
#preview.resizing {
pointer-events: none;
}
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
<div class="pane left">
This is the left pane.
</div>
<div class="pane center_container">
<div class="gutter gutter-v"></div>
<div class="pane center1">
This is the center pane1
</div>
<div class="pane">
<div class="gutter gutter-h"></div>
This is the center pane2.
</div>
</div>
<div class="pane">
<div class="gutter gutter-v"></div>
<iframe id="preview"></iframe>
</div>
</div>