javascript - 类似 iPhoneX 通过拖动显示/隐藏菜单/容器

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

我想实现当用户拖动 .drag 元素时根据拖动值平滑折叠灰色 .content-wrapper block (内部有蓝色方 block )的能力。如今移动触摸拖动最好、最有效的方法是什么?

* {
  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>

最佳答案

这是我使用 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>

关于javascript - 类似 iPhoneX 通过拖动显示/隐藏菜单/容器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51918455/

相关文章:

c# - 拖放在 C# Winforms 应用程序中不起作用

python - 在多个 QTreeWidget 之间拖放数据

javascript - 这是如何运作的?类型 = 类型 || 'any' ;

javascript - 来自index.html 文件中的javascript 的JSON

css - 未应用媒体查询

html - 谁能告诉我主 div 中这两个图像集的区别?

cocoa - 如何在 Mac OS X 10.5 中处理 Finder 中的多个文件拖放操作?

javascript - 保存后,内联编辑焦点不会失去焦点

javascript - jQuery UnSlider — 防止 slider 出现 "Rewinding"

PHP foreach、CSS 和jQuery 脚本..如何交互?