如您所见,我有三个面板(左、中、右),它们可以正确地水平zoom /调整大小.现在,我想在中央面板内插入一个新面板.

enter image description here

新的面板将不得不垂直调整大小(上下升起).我想要实现这一点在纯的Java脚本(没有jQuery或其他库),根据我的Java脚本代码.我是新来的,我遇到了麻烦.

我想要得到这个:

enter image description here

附言:自然,3个垂直面板(左,中,右)必须继续左右水平移动,因为他们已经正确地移动与我的代码.我不希望新增加的面板打破了其他面板已经在运行的运动.

这是我的代码:

const gutters = document.querySelectorAll(".gutter");
const gutter_orizontal = document.querySelectorAll(".gutter_new");

const panes = document.querySelectorAll(".pane");
const minWidth = 200;

function resizer(e) {
  window.addEventListener("mousemove", mousemove);
  window.addEventListener("mouseup", mouseup);

  let prevX = e.x;
  const currentPane = e.currentTarget.parentNode;
  const currentPanel = currentPane.getBoundingClientRect();
  const prevPane = currentPane.previousElementSibling;
  const prevPanel = prevPane.getBoundingClientRect();

  function mousemove(e) {
    let newX = prevX - e.x;
    let newCurrentWidth = currentPanel.width + newX;
    let newPrevWidth = prevPanel.width - newX;
    if (newCurrentWidth < minWidth || newPrevWidth < minWidth) return;
    currentPane.style.width = newCurrentWidth + "px";
    prevPane.style.width = newPrevWidth + "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 {
  padding: 1em;
  color: #fff;
  min-width: 200px;
}

.center {
  position: relative;
}

.right {
  position: relative;
  flex-grow: 1;
}

.new {
  position: relative;
}

.gutter {
  width: 10px;
  height: 100%;
  background: #666;
  position: absolute;
  top: 0;
  left: 0;
  cursor: col-resize;
}

.gutter_new {
  height: 10px;
  width: 100%;
  background: #666;
  position: absolute;
  top: 0;
  left: 0;
  cursor: row-resize;
}
<div class="wrapper">
  <div class="pane left">
    This is the left pane.
  </div>
  <div class="pane center">
    This is the center pane.
    <div class="gutter"></div>
    <div class="pane new">
      This is the new pane.
      <div class="gutter_new"></div>
    </div>
  </div>
  <div class="pane right">
    This is the right pane.
    <div class="gutter"></div>
  </div>
</div>

推荐答案

  1. 加两个班.gutter-hresizer()会改变.pane‘S的宽度或高度,这取决于.gutter’S级.

  2. 使用has() Select 器将成为其他.pane父对象的.pane更改为Flexbox.has()已经被最新的Firefox支持.

  3. MinHeight和minWidth现在有.wrapper种内联样式,所以你可以通过js获得它们.

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;
  padding: 1em;
  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;
}


/* 
the reason I delete .right is because I use .pane:last-child to select the last pane (the bottom one or the right one)
you can keep .left and .center  to set default width and height
but it's better to use some classes like .w-250px or .h-150px, it's easier to read and reuse
*/

.w-250px {
  width: 250px;
}

.h-150px {
  height: 150px;
}
<!-- use css variables so you only need to edit one place if you need to change min width or min height -->
<div class="wrapper" style="--min-width: 200px;--min-height: 100px;">
  <div class="pane w-250px">
    This is the left pane.
  </div>
  <div class="pane">
    <div class="gutter gutter-v"></div>
    <div class="pane h-150px">
      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>
    This is the right pane.
  </div>
</div>

Javascript相关问答推荐

仅圆角的甜甜圈图表

使用axios.获取实时服务器时的404响应

IMDB使用 puppeteer 加载更多按钮(nodejs)

在页面上滚动 timeshift 动垂直滚动条

无法在nextjs应用程序中通过id从mongoDB删除'

Angular 订阅部分相互依赖并返回数组多个异步Http调用

如何在每次单击按钮时重新加载HighChart/设置HighChart动画?

闭包是将值复制到内存的另一个位置吗?

在数组中查找重叠对象并仅返回那些重叠对象

JavaScript不重定向配置的PATH

如何在Java脚本中对列表中的特定元素进行排序?

JS Animate()方法未按预期工作

当从其他文件创建类实例时,为什么工作线程不工作?

对具有相似属性的对象数组进行分组,并使用串连的值获得结果

背景动画让网站摇摇欲坠

构建器模式与参数对象输入

本地损坏的Java脚本

调用特定数组索引时,为什么类型脚本不判断未定义

Promise.race()返回已解析的promise ,而不是第一个被拒绝的promise

在每次重新加载页面时更改指针光标