两个区域的垂直可拖动划分

Posted

技术标签:

【中文标题】两个区域的垂直可拖动划分【英文标题】:Vertically Draggable Division of Two Areas 【发布时间】:2016-04-01 01:46:38 【问题描述】:

我想对两个区域进行垂直可拖动的划分,如下所示。

我只想将可拖动 div 的online example 修改为我想要的。最后,我得到了this。有人可以给我一些修改它的提示吗?


JSFiddle 链接:https://jsfiddle.net/casperhongkong/omekvtka/14/


HTML

<div class="container">
  <div class="area1">
Area 1
  </div>
  <div class="drag">

  </div>
  <div class="area2">
Area 2
  </div>
</div>

CSS

.container 
  position: fixed;
  top: 51px;
  right: 0px;
  bottom: 0px;
  left: 0px;
  background-color: #272822;
  border: 1px solid #222;
 // margin: 0 auto;
  //display: inline-block;


.area1 
  position: absolute;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;


.drag 
  position: fixed;

  width: 5px;
  height: 100%;
  background-color: #444;
  display: inline-block;


.area2 
  position: absolute;
  right: 0;
  height: 100%;
  width: 30%;
  background-color: #ddd;
  display: inline-block;


JavaScript

$(document).ready(function() 

  $('.drag').on('mousedown', function(e) 
    var $area1 = $('.area1'),
        $area2 = $('.area2'),
        startWidth_a1 = $area1.width(),
        startWidth_a2 = $area2.width(),
        pX = e.pageX;

    $(document).on('mouseup', function(e) 
      $(document).off('mouseup').off('mousemove');
    );

    $(document).on('mousemove', function(me) 
      var mx = (me.pageX - pX);
      $area1.css(
        width: startWidth_a1 - mx;
      );
      $area2.css(
        //left: mx / 2,
        width: startWidth_a2 - mx,
        //top: my
      );
    );

  );
);

【问题讨论】:

我强烈推荐 split.js 这个nathancahill.github.io/Split.js split.js 的链接已失效。现在是split.js.org 【参考方案1】:

对于 javascript,我建议查看一个库,因为这比几行代码要复杂得多。 @fauxserious 以 Split.js 为例。

这在纯 html/CSS 中是可能的,尽管略有限制,正如 here 所讨论的那样。

HTML:

<div class="split-view">
    <div class="resize-x panel" style="width: 216px;">
      Panel A
    </div>
    <div class="panel">
      Panel B
    </div>
</div>

CSS:

/* Panels: */
.panel 
    padding: 1em; 
    border-width: 6px; 
    border-style: solid; 
    height: 4em; 


/* Resizing */
.resize-x  
    resize: horizontal;
    overflow: auto;


/* Split View */
.split-view 
    margin: 1em 0; 
    width: 100%;
    clear: both;
    display: table;


.split-view .panel 
    display: table-cell;

【讨论】:

阻力太小了。能不能大一点?【参考方案2】:

基于@afischer 的表格单元解决方案,这里有一个替代方案。 我不得不将手风琴放在左侧面板中。 手风琴的粘性标题需要溢出可见, 虽然调整大小要求溢出不可见:https://caniuse.com/#feat=css-sticky. 同时,我不需要在右侧面板中放置任何东西。

因此,克服的方法是在右侧面板上使用调整大小,并旋转 180 度以使可拖动的一侧到中间,以及这样可拖动的角重新定位到顶部(无需滚动即可看到)。 此外,可拖动的角落还添加了一些亮点。

/* Panels: */
.panel 
  padding: 1em; 
  border-width: 6px; 
  border-style: solid; 
  height: 4em; 


/* Resizing */
.resize-x  
  resize: horizontal;
  overflow: auto;
  transform: rotate(180deg);
  border-right: solid gray 1px;


/* Split View */
.split-view 
  margin: 1em 0; 
  width: 100%;
  clear: both;
  display: table;


.split-view .panel 
  display: table-cell;


.resize-x::-webkit-resizer 
    border-width: 8px;
    border-style: solid;
    border-color: transparent orangered orangered transparent;
  
<div class="split-view">
    <div
      class="panel"
      style="width: 216px;">
        Panel A
    </div>
    <div class="panel resize-x">
      Panel B
    </div>
</div>

不幸的是,上面有两个令人失望的事情:

Firefox 无法处理表格单元格和调整大小的组合 只有抓取器的一角是响应式的,甚至可以轻松滚动出来

这是另一个解决方案,它也考虑了上述两个问题

没有调整 CSS 属性的大小 并带有全高响应式抓取器

它是 flexbox 和 input:range 滑块的组合。

诀窍在于指针事件 CSS 属性可以不同

在滑块的背景上 在它的抓取器上。

滑块覆盖整个视图。滑块的背景对于事件也是透明的(指针事件:无),而拖动条本身会捕获事件(指针事件:自动)。

它需要少量的 Javascript,并且因为我在 Nuxt.js 中实现了生产版本,所以我在这里使用 Vue.js,而不是 vanilla JS。

new Vue(
        el: '#vue',

        data: 
          windowWidth: null,
          splitWidth: null,
        ,

        mounted() 
          this.windowWidth = window.innerWidth;
          // For arbitrary initial position:
          this.splitWidth = this.windowWidth * 2/3;
        ,

        computed: 
          flexRatio() 
            return this.splitWidth / this.windowWidth;
          
        

      )
body 
        margin:0;
      

      main 
        display: flex;
        width: 100%;
        height: 100vh;
      

      article 
        display: flex;
      

      section 
        width: 100%;
        height: 100%;
        text-align: justify;
        padding: 20px;
      

      .section-left 
        background-color: darkseagreen;
      

      .section-right 
        background-color: orangered;
      

      #split-grabber 
        pointer-events: none;
        position: fixed;
        top: 0; right: 0; bottom: 0; left: 0;
        -webkit-appearance: none;
      /* Safari allows dragging behind scroll bar.
        We fix it by shrinking its width on the right side via both
        its range value      :max="windowWidth - 12"
        and its width (CSS)   width: calc(100% - 12px)
        ...synchronously  */
        width: calc(100% - 12px);
        height: 100vh;
        background: transparent;
        outline: none;
        margin: 0;
      

      #split-grabber::-webkit-slider-thumb 
        z-index: 1;
        pointer-events: auto;
        -webkit-appearance: none;
        appearance: none;
        width: 5px;
        height: 100vh;
        background: lightgray;
        box-shadow: 1px 2px 2px 0px gray;
        cursor: col-resize;
      

      #split-grabber::-moz-range-thumb 
        z-index: 1;
        pointer-events: auto;
        -webkit-appearance: none;
        appearance: none;
        width: 5px;
        height: 100vh;
        background: lightgray;
        box-shadow: 1px 2px 2px 0px gray;
        cursor: col-resize;
      
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<main id="vue">
      <!-- Safari allows dragging behind scroll bar
      We fix it by shrinking its width on the right side via both
      its range value      :max="windowWidth - 12"
      and its width (CSS)   width: calc(100% - 12px)
      ...synchronously  -->
      <input
        id="split-grabber"
        type="range" 
        v-model="splitWidth"
        :max="windowWidth - 12"
      >
      <article
      class="article"
      :style="'flex': flexRatio"
      >
        <section
        class="section section-left">
          splitWidth: splitWidth px<br>
          “There was a rich man who always dressed in the finest clothes and lived in luxury every day.
          And a very poor man named Lazarus, whose body was covered with sores, was laid at the rich man’s gate.
          He wanted to eat only the small pieces of food that fell from the rich man’s table. And the dogs would come and lick his sores.
          Later, Lazarus died, and the angels carried him to the arms of Abraham. The rich man died, too, and was buried.
          In the place of the dead, he was in much pain. The rich man saw Abraham far away with Lazarus at his side.
          He called, ‘Father Abraham, have mercy on me! Send Lazarus to dip his finger in water and cool my tongue, because I am suffering in this fire!’
        </section>  
      </article>
      <article
        class="article"
        :style="'flex': 1-flexRatio"  
      >
        <section class="section section-right">
          But Abraham said, ‘Child, remember when you were alive you had the good things in life, but bad things happened to Lazarus. Now he is comforted here, and you are suffering.
          Besides, there is a big pit between you and us, so no one can cross over to you, and no one can leave there and come here.’
          The rich man said, ‘Father, then please send Lazarus to my father’s house.
          I have five brothers, and Lazarus could warn them so that they will not come to this place of pain.’
          But Abraham said, ‘They have the law of Moses and the writings of the prophets; let them learn from them.’
          The rich man said, ‘No, father Abraham! If someone goes to them from the dead, they would believe and change their hearts and lives.’
          But Abraham said to him, ‘If they will not listen to Moses and the prophets, they will not listen to someone who comes back from the dead.’”        
        </section>
      </article>
    </main>

【讨论】:

以上是关于两个区域的垂直可拖动划分的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 jquery ui 可拖动突出显示悬停时的可放置​​区域

jQuery-ui 可拖动滚动仅垂直

如何使 div 可拖动和可放置

可拖动+可排序和可滚动的 div

允许 Gridstack 仅可拖动到项目的特定区域

使用 jquery ui 可拖动,是不是可以有不同的滚动灵敏度垂直和水平?