制作拖动条以调整 CSS 网格内的 div 大小

新手上路,请多包涵

我在一个独特的容器 div 中有 2 个盒子和一条垂直 div 线(下面的代码和小提琴)。

我正在使用 CSS 网格将我的元素定位在容器内

我想要完成的是使用垂直线根据垂直线的位置水平调整两个框的大小。

如果这个问题很笨,我深表歉意,我是网络开发的新手,之前只使用过 Python,已经尝试过谷歌和 stackoverflow 搜索,但所有解决方案似乎都过于复杂,通常需要额外的库,我一直在寻找更简单的东西和 JS。

HTML:

 <div class="wrapper">
  <div class="box a">A</div>
  <div class="handler"></div>
  <div class="box b">B</div>
</div>

CSS:

 body {
  margin: 40px;
}

.wrapper {
  display: grid;
  grid-template-columns: 200px 8px 200px;
  grid-gap: 10px;
  background-color: #fff;
  color: #444;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
  font-size: 150%;
  resize: both;
}

.handler{
    width: 3px;
    height: 100%;
    padding: 0px 0;
    top: 0;
    background: red;
    draggable: true;
}

https://jsfiddle.net/gv8Lwckh/6/

原文由 Aquazi 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 186
1 个回答

您打算做的事情可以使用 CSS flexbox 来完成——不需要使用 CSS 网格。坏消息是 HTML + CSS 不是那么聪明,声明 resizedraggable 将使布局灵活并可通过用户交互进行调整。为此,您将不得不使用 JS。好消息是这实际上并不太复杂。

这是输出以下代码的快速屏幕截图:

但是,为了让您理解我将在下面发布的代码,您必须熟悉以下内容:

  • 事件绑定使用 .addEventListener 。在这种情况下,我们将使用 mousedownmouseupmousemove 的组合来确定用户是否正在拖动元素
  • CSS 弹性盒布局

解决方案说明

使用 CSS 进行初始布局

首先,您需要使用 CSS flexbox 来布局您的盒子。我们简单的在parent上声明 display: flex ,然后使用 flex: 1 1 auto (翻译过来就是“让元素变大,让元素变小,等宽”),这样的布局才有效在页面的初始呈现:

 .wrapper {
  /* Use flexbox */
  display: flex;
}

.box {
  /* Use box-sizing so that element's outerwidth will match width property */
  box-sizing: border-box;

  /* Allow box to grow and shrink, and ensure they are all equally sized */
  flex: 1 1 auto;
}

听拖动交互

您想要监听可能源自您的 .handler 元素的鼠标事件,并且您想要一个全局标志来记住用户是否正在拖动:

 var handler = document.querySelector('.handler');
var isHandlerDragging = false;

然后你可以使用以下逻辑来检查用户是否正在拖动:

 document.addEventListener('mousedown', function(e) {
  // If mousedown event is fired from .handler, toggle flag to true
  if (e.target === handler) {
    isHandlerDragging = true;
  }
});

document.addEventListener('mousemove', function(e) {
  // Don't do anything if dragging flag is false
  if (!isHandlerDragging) {
    return false;
  }

  // Set boxA width properly
  // [...more logic here...]
});

document.addEventListener('mouseup', function(e) {
  // Turn off dragging flag when user mouse is up
  isHandlerDragging = false;
});

计算盒子 A 的宽度

现在剩下的就是计算框 A 的宽度(插入到上面代码中的 [...more logic here...] 占位符中),使其与鼠标移动的宽度相匹配。 Flexbox 将确保盒子 B 将填满剩余空间:

 // Get offset
var containerOffsetLeft = wrapper.offsetLeft;

// Get x-coordinate of pointer relative to container
var pointerRelativeXpos = e.clientX - containerOffsetLeft;

// Resize box A
// * 8px is the left/right spacing between .handler and its inner pseudo-element
// * Set flex-grow to 0 to prevent it from growing
boxA.style.width = (pointerRelativeXpos - 8) + 'px';
boxA.style.flexGrow = 0;


工作示例

 var handler = document.querySelector('.handler');
var wrapper = handler.closest('.wrapper');
var boxA = wrapper.querySelector('.box');
var isHandlerDragging = false;

document.addEventListener('mousedown', function(e) {
  // If mousedown event is fired from .handler, toggle flag to true
  if (e.target === handler) {
    isHandlerDragging = true;
  }
});

document.addEventListener('mousemove', function(e) {
  // Don't do anything if dragging flag is false
  if (!isHandlerDragging) {
    return false;
  }

  // Get offset
  var containerOffsetLeft = wrapper.offsetLeft;

  // Get x-coordinate of pointer relative to container
  var pointerRelativeXpos = e.clientX - containerOffsetLeft;

  // Arbitrary minimum width set on box A, otherwise its inner content will collapse to width of 0
  var boxAminWidth = 60;

  // Resize box A
  // * 8px is the left/right spacing between .handler and its inner pseudo-element
  // * Set flex-grow to 0 to prevent it from growing
  boxA.style.width = (Math.max(boxAminWidth, pointerRelativeXpos - 8)) + 'px';
  boxA.style.flexGrow = 0;
});

document.addEventListener('mouseup', function(e) {
  // Turn off dragging flag when user mouse is up
  isHandlerDragging = false;
});
 body {
  margin: 40px;
}

.wrapper {
  background-color: #fff;
  color: #444;
  /* Use flexbox */
  display: flex;
}

.box {
  background-color: #444;
  color: #fff;
  border-radius: 5px;
  padding: 20px;
  font-size: 150%;

  /* Use box-sizing so that element's outerwidth will match width property */
  box-sizing: border-box;

  /* Allow box to grow and shrink, and ensure they are all equally sized */
  flex: 1 1 auto;
}

.handler {
  width: 20px;
  padding: 0;
  cursor: ew-resize;
  flex: 0 0 auto;
}

.handler::before {
  content: '';
  display: block;
  width: 4px;
  height: 100%;
  background: red;
  margin: 0 auto;
}
 <div class="wrapper">
  <div class="box">A</div>
  <div class="handler"></div>
  <div class="box">B</div>
</div>

原文由 Terry 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题