不到30行, 用any-touch實現一個drawer

鐵皮飯盒發表於2019-03-27

https://github.com/383514580/any-touch

any-touch 一個手勢庫

demo

不到30行, 用any-touch實現一個drawer

預覽1

如果預覽1打不開, 點我

drawer的基本邏輯

  1. 新增2個div, 一個是當drawer隱藏的時候開啟隱藏的觸發開關, 一個是drawer本身.
  2. 對把手和drawer進行進行fixed定位到介面的右側邊緣.
  3. 調整drawer和把手的樣式, 這裡把手主要是要設定背景色為透明, 具體樣式看下面程式碼.
  4. any-touch分別給把手和drawer新增pan(拖拽)手勢.
  5. 當drawer隱藏時, 拖拽把手向右, 通過pan返回的deltaX(每次觸發拖拽的x偏移)進行drawer的拖拽, 讓其向右側移動以顯示.
  6. 向左拖拽drawer, 讓其隱藏, 當隱藏部分佔drawer寬度超過一半的時候, 鬆開手, 那麼抽屜自動隱藏到左側, 反之, drawer完全顯示.

: 本文僅用來講解drawer的基本原理, 還有很多邊界處理的細節大家可以後續自行補充作為練習.

程式碼

<!-- 觸發把手 -->
<div class="com-drawer-handler" id="j-com-drawer-handler"></div>

<!-- 抽屜 -->
<div class="com-drawer" id="j-com-drawer">
   <img class="avator" src="https://s.cdpn.io/profiles/user/406915/80.jpg?1511329408" width="100%">
  
  <p align="center">
    鐵皮飯盒
  </p>
  <a class="github" href="https://github.com/383514580/any-touch">github : any-touch</a>
<div>
  <script src="https://unpkg.com/any-touch/dist/AnyTouch.umd.js"></script>
複製程式碼
.com-drawer-handler {
  height: 100vh;
  background: rgba(252, 252,252, 0);
  width: 45px;
  position: fixed;
  z-index: 2;
  top: 0;
  left: 0;
}

.com-drawer {
  padding: 30px;
  height: 100vh;
  min-width: 10vw;
  position: fixed;
  top: 0;
  left: 0;
  z-index: 3;
  box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.1);
  .avator {
    touch-action: none;
    display: block;
    width: 60%;
    border-radius: 100%;
    margin: 15px auto;
  }
  .github {
    padding: 5px 15px;
    background: #000;
    color: #fff;
    text-decoration: none;
    display: block;
    text-align: center;
    border-radius: 6px;
    margin-top: 60px;
  }
}

.animated {
  transition: all 200ms;
}

複製程式碼
// 抽屜部分
let offsetX = 0;
const elDrawer = document.getElementById("j-com-drawer");
const minX = 0 - elDrawer.offsetWidth;
const at = new AnyTouch(elDrawer);
at.on("panmove", ({ deltaX }) => {
  offsetX += deltaX;
  if (0 <= offsetX) {
    offsetX = 0;
  }
  elDrawer.style.transform = `translateX(${offsetX}px)`;
});
at.on("panend", () => {
  offsetX = minX / 2 < offsetX ? 0 : minX;
  elDrawer.style.transform = `translateX(${offsetX}px)`;
  elDrawer.classList.toggle(animated, true);
});

// 把手
const elHandler = document.getElementById("j-com-drawer-handler");
const atHandler = new AnyTouch(elHandler, { isPreventDefault: false });
atHandler.on("panmove", ({deltaX}) => {
  offsetX+= deltaX;
  offsetX = 0 < offsetX ? 0 : offsetX;
  elDrawer.style.transform = `translateX(${offsetX}px)`;
});
複製程式碼

關於vue和react版本

這裡是用純js實現的版本, 如果用vue或者react程式碼量會更少, 有興趣的同學可以自行實現或者需要的人多, 我會再寫個vue版本的例子(react我也不會, 我得找同事幫寫個demo, 嘿). 太晚了,寫的倉促, 如果錯誤請指出, 我會立即修改.

typescript

any-touch由typescript編寫, 如有興趣歡迎訪問我的其他幾篇關於程式碼講解的文章:

用typescript開發手勢庫 - (1)web開發常用手勢有哪些?

用TypeScript開發手勢庫 - (2)tsconfig.json & rollup.config.js & npx

用TypeScript開發手勢庫 - (3)統一化Mouse和Touch事件

相關文章