js 自适应缩放_css flex多列自适应布局 + js拖拽drag事件

css flex多列布局

通过flex实现多列布局代码如下

main.css主要代码:

.multi-col {
  display: flex;
  height: 700px;
}

.multi-col .col {
  height: 100%;
  box-sizing: border-box;
  position: relative;
  flex: 1 1 auto;
}

.multi-col .rigid {
  flex: 0 0 auto;
  padding-right: 3px;
}

#col1 { width: 200px; background: darkred; }
#col2 { width: 210px;  background: darkblue; }
#col3 { background: #777703; }
#col4 { background: white; }

index.html主要代码

<div class="mult-col-ctn">
  <div id="col1" class="col rigid"></div>
  <div id="col2" class="col rigid"></div>
  <div id="col3" class="col"></div>
  <div id="col4" class="col"></div>
</div>

最后效果如下

e89d283141b671cddbd7c9b2c587321d.png

Flex布局Flexbox Layout(Flexible Box)的核心是, 修改容器(Container)内部元素(items)的长宽和次序以更好的填充可用的空间.

上面的css代码非常简单, 通过css属性display: flex确定flex容器(flex container), 然后容器内部的为flex元素(flex items), 通过flex属性控制其填充容器的空间的方式.

flex属性由三部分组成: flex-grow, flex-shrinkflex-basis.

.flex-item {
    flex: <'flex-grow'> <'flex-shrink'> <'flex-basis'> 
}
  • flex-group: 定义元素的放大比例,默认为0. 当为0时, 不放大即使有剩余的空间
  • flex-shrink: 定义了项目的缩小比例,默认为1. 当为0时, 不缩小
  • flex-basis: 它的默认值为auto,元素的本来widthheight

js拖拽(drag)事件

通过拖拽事件(drag event)实现动态修改列的宽度.

首先在需要动态修改的列中, 添加拖动条.

.mult-col-ctn .col {
  /* .. */
  box-sizing: border-box;
  position: relative;
  padding-right: 3px;
}

.drag {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 3px;
  background: darkgray;
  cursor: ew-resize;
}

需要动态修改宽度的列, 不能自动放大flex-grow: 0, 不能自动缩小flex-shrink: 0, 保留原有尺寸flex-basis: auto. 即: flex: 0 0 auto.

<div id="col1" class="col rigid">
    <div class="drag"></div>
</div>
<div id="col2" class="col rigid">
    <div class="drag"></div>
</div>

html元素是默认是无法拖拽的, 需要修改draggable属性为true.

或修改html标签

<div class="drag" draggable="true"></div>

或通过js代码

ctn.querySelectorAll('.drag').forEach(elem => elem.draggable = true)

完整代码

index.html

<!doctype html>
<html>
  <meta charset="UTF-8">
  <title>TecPoste</title>
  <link type="text/css" rel="stylesheet" media="screen,print" href="main.css">
<head>
</head>
<body>
  <div class="multi-col">
    <div class="col rigid col1">
      <div class="drag"></div>
    </div>
    <div class="col rigid col2">
      <div class="drag"></div>
    </div>
    <div class="col col3"></div>
    <div class="col col4"></div>
  </div>

  <div class="multi-col">
    <div class="col rigid col1">
      <div class="drag"></div>
    </div>
    <div class="col rigid col2">
      <div class="drag"></div>
    </div>
    <div class="col col3"></div>
    <div class="col col4"></div>
  </div>
  <script type="text/javascript" src="main.js"></script>
</body>
</html>

main.css

.multi-col {
  display: flex;
  height: 300px;
  width: 900px;
  margin-bottom: 1rem;
  border: 1px solid black;
}

.multi-col .col {
  height: 100%;
  box-sizing: border-box;
  position: relative;
  flex: 1 1 auto;
}

.multi-col .rigid {
  flex: 0 0 auto;
  padding-right: 3px;
}

.drag {
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 3px;
  background: darkgray;
  cursor: ew-resize;
}

.col1 {
  width: 200px;
  background: darkred;
}

.col2 {
  width: 210px;
  background: darkblue;
}

.col3 {
  background: #777703;
}

.col4 {
  background: white;
}

main.js

const minColWidth = 100;

let currentCol = null;
let currentCtn = null;
let prevX = null;

const regMultiCol = (ctn) => {
  ctn.querySelectorAll('.drag').forEach(elem => elem.draggable = true);
};

const validColWidth = (ctn) => {
  const len = ctn.children.length;
  for (let i = 0; i < len; i++) {
    const col = ctn.children[i];
    if (col.offsetWidth <= minColWidth) {
      return false;
    }
  }
  return true;
};

document.addEventListener('dragstart', (evt) => {
  const drag = evt.target;
  if (!drag.classList.contains('drag')) {
    return;
  }

  currentCol = drag.parentElement;
  currentCtn = currentCol.parentElement;

}, false);

document.addEventListener('dragend', (evt) => {
  currentCol = null;
  currentCtn = null;
  prevX = null;
}, false);

document.addEventListener('dragover', (evt) => {
  prevX = prevX || evt.clientX;
  if (!currentCol || !currentCtn) {
    return;
  }

  const diff = evt.clientX - prevX;
  const width = currentCol.offsetWidth + diff;
  currentCol.style.width = width + 'px';

  if (!validColWidth(currentCtn)) {
    currentCol.style.width = (width - diff) + 'px';
    return;
  }

  prevX = evt.clientX;
  event.preventDefault();
}, false);

document.querySelectorAll('.multi-col').forEach(ctn => regMultiCol(ctn));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值