类似于iPhoneX的显示/隐藏菜单/容器

时间:2018-08-19 14:06:02

标签: javascript css drag-and-drop draggable hammer.js

我想实现在用户拖动.content-wrapper元素时根据拖动值平滑折叠灰色.drag块(内部为蓝色方块)的功能。如今,移动触摸拖动的最佳方法是什么?

* {
  box-sizing: border-box;
  color: white;
}

.drag {
  width: 50px;
  height: 3px;
  border-radius: 3px;
  opacity: 0.3;
  margin: 0 auto;
  background: linear-gradient(to left, white, rgba(255, 255, 255, 0.8) 50%, white 100%);
  transition: opacity 0.4s;
}

.screen {
  padding-top: 40px;
  margin: 0 auto;
  border-radius: 5px;
  overflow: hidden;
  background: #2b2d5b;
  width: 320px;
  height: 568px;
}

.controls {
  background: linear-gradient(to bottom, #fd2929, #fd5c5c);
  height: 100px;
  
}

.drag-wrapper {
  display: block;
  padding: 20px;
}

.drag-wrapper:active .drag,
.drag-wrapper:hover .drag,
.drag-wrapper:focus .drag {
  opacity: 0.7;
}

.board {
  padding: 0 20px;
}

.content-wrapper {
  padding: 20px;
  height: 320px;
}

.content-wrapper {
  background: #444;
}

.content {
display: flex;
justify-content: center;
align-items: center;
font-family: Helvetica;
  background: linear-gradient(to bottom, #3adffd, #00abfb);
  height: 100%;
}
<div class="screen">
  <div class="content-wrapper">
    <div class="content">
    .content
    </div>
  </div>
  <a href="javascript:void(0)" class="drag-wrapper">
    <div class="drag"></div>
  </a>
  <div class="board">
    <div class="controls"></div>
  </div>
</div>

1 个答案:

答案 0 :(得分:1)

这是我使用hammer.js

的情况的实现
  

http://hammerjs.github.io

board的运动可能基于e.velocityY进行更复杂的计算,但是当pan结束时我正在使用快速CSS过渡,这对我的情况很好

$(document).ready(function() {
    let sliderManager = new Hammer.Manager(document.querySelector('.drag-wrapper'));
    let board = document.querySelector('.board');
    let threshold = 150;
    let boardTopInitial = board.style.top = board.offsetTop;
    let boardTopCollaped = 30;
  
    sliderManager.add(new Hammer.Pan({
      threshold: 0,
      pointers: 0
    }));
    sliderManager.on('pan', function(e) {
      e.preventDefault();
      board.classList.remove("transitable");
      board.classList.add("full-height");
      if (!board.classList.contains('pinned-top') && e.deltaY < 0) {
        board.style.top = boardTopInitial + e.deltaY + "px";
        if (e.isFinal) {
          board.classList.add("transitable");
          if (Math.abs(e.deltaY) > threshold) {
            board.style.top = boardTopCollaped + "px";
            board.classList.add("pinned-top");
          } else {
            board.setAttribute('style', '');
            board.classList.remove("full-height");
          }
        }
      } else if (board.classList.contains('pinned-top') && e.deltaY > 0) {
        board.style.top = boardTopCollaped + e.deltaY + "px";
        if (e.isFinal) {
          board.classList.add("transitable");
          if (Math.abs(e.deltaY) > threshold) {
            board.setAttribute('style', '');
            board.classList.remove("pinned-top");
            board.classList.remove("full-height");
          } else {
            board.style.top = boardTopCollaped + "px";
            board.classList.add("top");
          }
        }
      }
    })
  })
* {
  box-sizing: border-box;
  color: white;
}

.drag {
  width: 50px;
  height: 3px;
  border-radius: 3px;
  opacity: 0.3;
  margin: 0 auto;
  background: linear-gradient(to left, white, rgba(255, 255, 255, 0.8) 50%, white 100%);
  transition: opacity 0.4s;
}

.pinned-top {
  top: 30px;
}

.full-height {
  box-shadow: none;
  min-height: 100vh;
}

.transitable {
  transition: top .2s ease-out;
}

.screen {
  position: relative;
  padding-top: 40px;
  margin: 0 auto;
  border-radius: 5px;
  overflow: hidden;
  background: #2b2d5b;
  width: 320px;
  height: 568px;
}

.controls {
  background: linear-gradient(to bottom, #fd2929, #fd5c5c);
  height: 100px;
}

.drag-wrapper {
  display: block;
  padding: 20px;
}

.drag-wrapper:active .drag,
.drag-wrapper:hover .drag,
.drag-wrapper:focus .drag {
  opacity: 0.7;
}

.board {
  padding: 0 20px;
  position: absolute;
  background: #2b2d5b;
  top: 360px;
  left: 0;
  right: 0;
}

.content-wrapper {
  padding: 20px;
  height: 320px;
}

.content-wrapper {
  background: #444;
}

.content {
  display: flex;
  justify-content: center;
  align-items: center;
  font-family: Helvetica;
  background: linear-gradient(to bottom, #3adffd, #00abfb);
  height: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://hammerjs.github.io/dist/hammer.min.js"></script>
<div class="screen">
  <div class="content-wrapper">
    <div class="content">
      .content
    </div>
  </div>
  <div class="board">
    <a href="javascript:void(0)" class="drag-wrapper">
      <div class="drag"></div>
    </a>
    <div class="controls"></div>
  </div>
</div>