动态布局 - 拖拽调整宽度

项目中出现需求,要求动态调整各个分块的大小,方便缩放查看信息,以下实现了宽度的动态调整(高度的后续会补上)

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
    <style media="screen">
      html,body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
      .flex-dragable {
        display: flex;
      }
      .flex-row {
        height: 80%;
        display: flex;
        flex-direction: column;
      }
      .flex-item {
        flex: 1 1 100%;
        padding: 15px;
        margin: 5px;
        border: 1px solid #a3a3a3;
        overflow: auto;
      }
      .flex-row-item {
        flex: 1 1 100%;
      }
    </style>
  </head>
  <body>
    <div class="flex-row">
      <div class="flex-dragable flex-row-item">
        <div class="flex-item">
          content 1 ...
        </div>
        <div class="flex-item">
          content 2 ...
        </div>
        <div class="flex-item">
          content - ...
        </div>
      </div>
      <div class="flex-dragable flex-row-item">
        <div class="flex-item">
          content 3 ...
        </div>
        <div class="flex-item">
          content 4 ...
        </div>
      </div>
    </div>
  </body>
  <script type="text/javascript">
    var items = document.querySelectorAll('.flex-dragable');

    Array.from(items).map(function(item){
      dragablize(item);
    });

    /**
    * 初始化拖拽
    **/
    function dragablize(ctn) {
      var items = ctn.querySelectorAll('.flex-item'), lastX;

      Array.from(items).map(function(item){
        item.onmousedown = function(event) {
          var target = getTarget(event),
              prevItem = target.previousElementSibling,
              suffItem = target.nextElementSibling;

          lastX = event.clientX;
          if (suffItem && (event.offsetX > this.offsetWidth - 10)) {
            item.mouseDown = true;
            item.oldX = event.x;
            item.oldWidth = item.offsetWidth;
          }else if(prevItem && (event.offsetX < 10)) {// 左边拖拽时,实际设置前置元素的宽度
            var evt = newMouseEvent(event,'mousedown');
            prevItem.dispatchEvent(evt);
          }
        };

        item.onmouseup = function(event) {
          var target = getTarget(event),
              prevItem = target.previousElementSibling;

          item.mouseDown = false;
          item.style.cursor = '';
          lastX = null;

          if(prevItem) {// 左边拖拽时触发前置元素mouseup,避免响应异常
            var evt = newMouseEvent(event,'mouseup');
            prevItem.dispatchEvent(evt);
          }
        };
      });

      ctn.onmousemove = function(event) {
        var target = getTarget(event);
        if(Array.from(items).includes(target)) {
          var prevItem = target.previousElementSibling,
              suffItem = target.nextElementSibling,
              direction = event.clientX - lastX;

          /**
          * 改变鼠标样式
          * 1:中间的元素左右边都可拖拽样式(左边拖拽时,实际设置前置元素宽度)
          * 2:没有前置元素的只能有右边拖拽样式
          * 3:没有后置元素的只能有左边拖拽样式
          **/
          if (suffItem && (event.offsetX > target.offsetWidth - 10)
              || prevItem && (event.offsetX < 10)) {
            target.style.cursor = 'col-resize';
          }else {
            target.style.cursor = '';
          }

          //调整宽度
          var item = getClickedTarget(items);
          if(item && item.mouseDown && direction) {
            setWidth(item,direction);
            lastX = event.clientX;
          }
        }
      };

      function setWidth(item,offset) {
        var style = getComputedStyle(item),
            width = style.width.replace('px','')-0;
        // maxWidth、minWidth 防止flex布局对宽度计算的影响
        item.style.width = width + offset + 'px';
        item.style.maxWidth = width + offset + 'px';
        item.style.minWidth = width + offset + 'px';
      }
    }

    function addListener(element,type,listener,useCapture){
        element.addEventListener?element.addEventListener(type,listener,useCapture):element.attachEvent("on" + type,listener);
    }
    function getTarget(evt){
        return evt.target || evt.srcElement;
    }
    function getClickedTarget(items){
        var t;
        Array.from(items).map(function(item){
          if(item.mouseDown == true) t = item;
        });
        return t;
    }
    /**
     * 创建鼠标事件
     **/
    function newMouseEvent(event,eventType){
        var clientX = event.clientX,clientY=event.clientY,screenX=event.screenX,screenY=event.screenY;

        var simEvent = new MouseEvent(eventType,{clientX:clientX,clientY:clientY,screenX:screenX,screenY:screenY});
        return simEvent;
    }
  </script>
</html>

 

posted @ 2019-05-28 19:23  【云】风过无痕  阅读(2148)  评论(0编辑  收藏  举报