javascript - 制作拖拽灵活分离器时的一个错误

标签 javascript jquery css flexbox splitter

我想在几个面板之间制作拖动分离器。互联网上有一些图书馆。我找到了a solution ,它很短并且独立于任何库(JQuery 除外)。

但是,有一个错误:当我们拖动第一个拆分器,然后拖动第二个拆分器,然后拖动第一个拆分器等时,有时拖动一个拆分器可能会影响另一个拆分器的位置。这当然不是我们所期望的。

有谁知道怎么解决吗?

(function($) {
  $.fn.drags = function(opt) {

    opt = $.extend({
      handle: "",
      cursor: "ew-resize",
      min: 10
    }, opt);

    if (opt.handle === "") {
      var $el = this;
    } else {
      var $el = this.find(opt.handle);
    }

    var priorCursor = $('body').css('cursor');

    return $el.css('cursor', opt.cursor).on("mousedown", function(e) {

      priorCursor = $('body').css('cursor');
      $('body').css('cursor', opt.cursor);

      if (opt.handle === "") {
        var $drag = $(this).addClass('draggable');
      } else {
        var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
      }
      var z_idx = $drag.css('z-index'),
        drg_h = $drag.outerHeight(),
        drg_w = $drag.outerWidth(),
        pos_y = $drag.offset().top + drg_h - e.pageY,
        pos_x = $drag.offset().left + drg_w - e.pageX;
      $drag.css('z-index', 1000).parents().on("mousemove", function(e) {

        var prev = $('.draggable').prev();
        var next = $('.draggable').next();

        // Assume 50/50 split between prev and next then adjust to
        // the next X for prev

        var total = prev.outerWidth() + next.outerWidth();

        console.log('l: ' + prev.outerWidth() + ', r:' + next.outerWidth());

        var leftPercentage = (((e.pageX - prev.offset().left) + (pos_x - drg_w / 2)) / total);
        var rightPercentage = 1 - leftPercentage;

        if (leftPercentage * 100 < opt.min || rightPercentage * 100 < opt.min) {
          return;
        }

        console.log('l: ' + leftPercentage + ', r:' + rightPercentage);

        prev.css('flex', leftPercentage.toString());
        next.css('flex', rightPercentage.toString());

        $(document).on("mouseup", function() {
          $('body').css('cursor', priorCursor);
          $('.draggable').removeClass('draggable').css('z-index', z_idx);
        });
      });
      e.preventDefault(); // disable selection
    });

  }
})(jQuery);

$('.handle').drags();
.flex-box {
  display: flex;
  width: 100%;
  margin: 0;
  height: 300px;
}
.flex-box .col {
  border: 1px solid green;
  flex: 0.33;
  padding: 12px;
  overflow-y: auto;
  overflow-x: hide;
}
.handle {
  width: 5px;
  text-align: center;
  color: white;
  transition: all ease-in 0.1s;
}
.draggable {
  background: pink;
}
body {}
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div class="flex-box">
    <div class="col">
      <h1>Drag The splitters</h1>
      <p>Pellentesque ...</p>
    </div>
    <div class="handle"></div>
    <div class="col">
      <h1>Magic</h1>
      <p>Pellentesque ...</p>
    </div>
    <div class="handle"></div>
    <div class="col">
      <h1>Magic 2</h1>
      <p>Pellentesque ...</p>
    </div>
  </div>
</body>
</html>

最佳答案

里面有几件事,我花了一些时间才弄清楚(我接受信用卡:P)

首先,一些事件一直令人着迷,例如 mouseup,我相信 mousemove 也是如此。

然后关于大小问题,您考虑的是拆分器周围的 2 个元素共享 100% 的 Flex 容器。 当你有 3 个或更多元素时,这当然是错误的。 我所做的只是获取调整大小操作所涉及的 2 个元素的 flexbox 的共享百分比:

var totalPercentage = parseFloat(prev.css('flex')) +  parseFloat(next.css('flex'));

有了这个并相应地更正公式,它就可以完美地工作。

(function($) {
  $.fn.drags = function(opt) {

    opt = $.extend({
      handle: "",
      cursor: "ew-resize",
      min: 10
    }, opt);

    if (opt.handle === "") {
      var $el = this;
    } else {
      var $el = this.find(opt.handle);
    }

    var priorCursor = $('body').css('cursor');

    return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
      
      priorCursor = $('body').css('cursor');
      $('body').css('cursor', opt.cursor);

      if (opt.handle === "") {
        var $drag = $(this).addClass('draggable');
      } else {
        var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
      }
      
      var z_idx = $drag.css('z-index'),
        drg_h = $drag.outerHeight(),
        drg_w = $drag.outerWidth(),
        pos_y = $drag.offset().top + drg_h - e.pageY,
        pos_x = $drag.offset().left + drg_w - e.pageX;
      
      var mouseMove = function(e) {
        
        //console.log("mousemove");
        var prev = $('.draggable').prev();
        var next = $('.draggable').next();

        // Assume 50/50 split between prev and next then adjust to
        // the next X for prev

        var total = prev.outerWidth() + next.outerWidth();
        
        var totalPercentage = parseFloat(prev.css('flex')) +  parseFloat(next.css('flex'));

        //console.log('l: ' + prev.outerWidth() + ', r:' + next.outerWidth());
        var offset = prev.offset();
        if(offset){
          
          var leftPercentage = ((e.pageX - offset.left - drg_w / 2) / total) * totalPercentage;
          var rightPercentage = totalPercentage - leftPercentage;

          if (leftPercentage * 100 < opt.min || rightPercentage * 100 < opt.min) {
            return;
          }

          //console.log('l: ' + leftPercentage + ', r:' + rightPercentage);
          
          prev.css('flex', leftPercentage.toString());
          next.css('flex', rightPercentage.toString());
        }
      }
      
      $drag.css('z-index', 1000).parent().on("mousemove", mouseMove).on("mouseup", function() {
            //console.log("mouseup");
            $(this).off("mousemove", mouseMove).off("mouseup");
            $('body').css('cursor', priorCursor);
            $('.draggable').removeClass('draggable').css('z-index', z_idx);
        });
      e.preventDefault(); // disable selection
    });
    
    
  }
})(jQuery);

$('.handle').drags();
.flex-box {
  display: flex;
  width: 100%;
  margin: 0;
  height: 300px;
}
.flex-box .col {
  border: 1px solid green;
  flex: 0.33;
  padding: 12px;
  overflow-y: auto;
  overflow-x: hide;
}
.handle {
  width: 5px;
  text-align: center;
  color: white;
  transition: all ease-in 0.1s;
}
.draggable {
  background: pink;
}
body {}
<!DOCTYPE html>
<html>
<head>
  <script src="https://code.jquery.com/jquery-3.1.0.js"></script>
  <title>JS Bin</title>
</head>
<body>
  <div class="flex-box">
    <div class="col">
      <h1>Drag The splitters</h1>
      <p>Pellentesque ...</p>
    </div>
    <div class="handle"></div>
    <div class="col">
      <h1>Magic</h1>
      <p>Pellentesque ...</p>
    </div>
    <div class="handle"></div>
    <div class="col">
      <h1>Magic 2</h1>
      <p>Pellentesque ...</p>
    </div>
  </div>
</body>
</html>

关于javascript - 制作拖拽灵活分离器时的一个错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41289292/

相关文章:

javascript - 火狐网络扩展。访问内容脚本中的弹出内容

jquery - iOS Chrome 给出了错误的窗口高度

html - 带有视频的 div 中的负左边框?

html - 更改悬停效果

html - 当使用 bootstrap 4 和 AngularMaterial2 减小屏幕尺寸时,文本不对齐

javascript - 如何将数组中的数字加在一起

javascript - 当我使用它时,jquery 单击绑定(bind)不起作用

javascript - 使用 valums ajax uploader 从上传列表中删除特定文件

javascript - Jquery按钮切换显示隐藏div

javascript - 超过最大调用堆栈大小 - 知道为什么(函数太多)但如何解决?