最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue側滑菜單組件——DrawerLayout

 更新時間:2017年12月18日 13:58:45   作者:AlexanderHuang  
本文介紹一個簡單的DrawerLayout(類似Android的DrawerLayout)布局組件的實現(xiàn),基于Vue.js側滑菜單組件的實現(xiàn)代碼大家通過本文一起學習吧

本文介紹一個簡單的DrawerLayout(類似Android的DrawerLayout)布局組件的實現(xiàn),基于Vue.js。介紹的內容已經制作成 vue-drawer-layout 組件。

前言

大家有興趣先用手機掃一掃這個二維碼,或者點我

然后點擊頁面中左上角的頭像打開drawer或者向右向左拖拽,就可以看到下面gif的效果,打開自己的手機QQ,是不是很像:)

 

谷歌官方把這種布局叫做DrawerLayout(抽屜式導航欄)。那么我們要如何實現(xiàn)呢,好了正片開始!

HTML結構

頁面結構很簡單,一個抽屜,一個主容器,內容可以利用slot支持外部自行定制。

<div class="drawer-layout">
  <!--抽屜-->
  <div class="drawer-wrap">
    <slot name="drawer"></slot>
  </div>
  <!--主容器-->
  <div class="content-wrap">
    <!--遮罩-->
    <div class="drawer-mask"></div>
    <slot name="content"></slot>
  </div>
</div>

抽屜一開始是隱藏在左側屏幕外的,故設置 left:-100% 使其整個都藏在外部

使用Touch

首先,判斷瀏覽器是否支持 touchEvent

let isTouch = 'ontouchstart' in window;
  let mouseEvents = isTouch ?
    {
      down: 'touchstart',
      move: 'touchmove',
      up: 'touchend',
      over: 'touchstart',
      out: 'touchend'
    } :
    {
      down: 'mousedown',
      move: 'mousemove',
      up: 'mouseup',
      over: 'mouseover',
      out: 'mouseout'
    };

綁定 touchdown 事件

document.addEventListener(mouseEvents.down, initDrag, false);

先定義一些變量,手指按下的x坐標記為 startX ,滑動中手指的位置x坐標記為 nowX ,drawer的x坐標偏移量記為 startPos

let startX, nowX, startPos;

觸發(fā) touchstart 時,記錄起始位置并綁定 touchmove ,注意:如果是 mouseEvent ,通過 e.clientX 來獲取當前的x坐標,如果是 touchEvent ,要通過 e.changedTouches[0].clientX 來獲取x坐標

const initDrag = function (e) {
  startX = e.clientX || e.changedTouches[0].clientX; //記錄手指按下的位置
  startPos = this.pos; //記錄drawer的上次位置
  document.addEventListener(mouseEvents.move, drag, false);
  document.addEventListener(mouseEvents.up, removeDrag, false);
}.bind(this);
const drag = function (e) {
  nowX = e.clientX || e.changedTouches[0].clientX; //滑動中手指的位置x坐標
  let pos = startPos + nowX - startX; 
  pos = Math.min(width, pos); //不能超過滑動最大值
  pos = Math.max(0, pos); //不能小于0
  this.pos = pos; //設置滾動距離為拖動的距離
}.bind(this);

那么,手指滑動的距離就是 nowX - startX ,當前drawer的位置為 startPos + nowX - startX ,這樣抽屜已經跟隨手指向右移動了,并且不會超過我們設置的拖動最大值。

區(qū)分垂直滑動和水平滑動

接下來你會發(fā)現(xiàn)一個問題,當手指垂直滾動主內容時,向右滑動手指也會拖出抽屜,這時應該做一件事:區(qū)分垂直滑動和水平滑動

當然,辦法有很多,這里先介紹一種利用三角函數(shù)來判定的方法

 

假設,上圖中的每個箭頭是手指滑動的方向,綠色箭頭代表可以拖出抽屜,紅色箭頭代表不可以拖出(注意,紅色箭頭也是有x坐標的偏移量的)。即當不可以拖出抽屜時,應觸發(fā)默認事件,比如垂直方向的滾動等等。

當手指按下觸發(fā) touchstart 時,記錄初始位置P 0 ;當滑動手指時,觸發(fā)的第一次 touchmove 時,記錄位置P 1 ,我們將P 0 到P 1 的矢量記為S(原諒我這個靈魂畫手)

 

這時候很容易看出,∠θ大于某個值時,比如30度,就可能是垂直方向的滾動操作而不是拖動抽屜。所以,可以根據(jù) y/x>tan30°

得到判斷條件:

if (isVerticle === undefined) isVerticle = Math.abs(nowY - startY) / Math.abs(nowX - startX) > (Math.sqrt(3) / 3);

當 isVerticle 為 true 時,不執(zhí)行drawer的拖動

讓Drawer動起來

我們使用css3的 transition 屬性使drawer具有過渡動畫效果,這里寫一個 moving 類

.moving
  transition transform .3s ease

別忘了加上class綁定,拖動時是不需要過渡動畫的(要跟隨手指),而松開手指時才需要過渡動畫。

<div class="drawer-wrap" :class="{'moving':moving,'will-change':willChange}"
   :style="{width:`${width}px`,left:`-${width)}px`,transform:`translate3d(${pos}px,0,0)`}">
  <slot name="drawer"></slot>
</div>

所以綁定 touchend 事件的方法時要做這些步驟

const removeDrag = function (e) {
  if (isVerticle !== undefined) {
    if (!isVerticle) {//當判定為抽屜拖動才進入
      let pos = this.pos;
      this.visible = pos > width * 3 / 5 //當前位置如果大于總寬度的3/5就判定為全部展開抽屜,否則將抽屜彈回隱藏
      if (this.pos > 0 && this.pos < width) this.moving = true;//如果位置已經處于最小值或最大值處,不需要有動畫效果了
    }
    this.pos = this.visible ? width : 0;
  }
  if (!this.moving) {
    this.willChange = false; //留個懸念
  }
  isVerticle = undefined;
  //取消touchmove和touchend事件綁定
  document.removeEventListener(mouseEvents.move, drag, false);
  document.removeEventListener(mouseEvents.up, removeDrag, false);
}.bind(this);

上面你可能發(fā)現(xiàn)代碼里有個 this.willChange = false ,它是干啥的捏?下面我們請出css的 will-change 大法

.will-change
    will-change transform

CSS 屬性 will-change 為web開發(fā)者提供了一種告知瀏覽器該元素會有哪些變化的方法,這樣瀏覽器可以在元素屬性真正發(fā)生變化之前提前做好對應的優(yōu)化準備工作。 這種優(yōu)化可以將一部分復雜的計算工作提前準備好,使頁面的反應更為快速靈敏。

其實是我們在 touchstart 可以預先告知瀏覽器抽屜可能要發(fā)生位移

const initDrag = function (e) {
  //...
  this.willChange = true;
}.bind(this);

當然最后別忘了在 transitionend 事件后把 transition 和 will-change 去掉,讓瀏覽器歇一會兒~

還有什么可以優(yōu)化的?

上面說的已經基本上把主要功能實現(xiàn)了,但是這其中還有沒有哪里可以優(yōu)化的?

 

咦? passive

是什么鬼?

網站使用被動事件偵聽器以提升滾動性能,在您的觸摸和滾輪事件偵聽器上設置 passive 選項可提升滾動性能具體看這里

原來這是現(xiàn)代瀏覽器的一個新特性,我們需要以新的方式來綁定我們的touch事件,當然首先先檢測一下是否支持 passive

const supportsPassive = (() => {
  let supportsPassive = false;
  try {
    const opts = Object.defineProperty({}, 'passive', {
      get: function () {
        supportsPassive = true;
      }
    });
    window.addEventListener("test", null, opts);
  } catch (e) {
  }
  return supportsPassive;
})();

于是我們的綁定事件代碼變成這樣

document.addEventListener(mouseEvents.move, drag, supportsPassive ? {passive: true} : false);

寫在最后

本文介紹了實現(xiàn)抽屜式導航欄的主要過程,詳細代碼已封裝成 vue-drawer-layout 組件,支持更豐富的定制和使用方式,具體文檔可以訪問我的github 或者npm官網檢索。

相關文章

  • Vue實現(xiàn)星級評價效果

    Vue實現(xiàn)星級評價效果

    這篇文章主要為大家詳細介紹了Vue實現(xiàn)星級評價效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Element?table?上下移需求的實現(xiàn)

    Element?table?上下移需求的實現(xiàn)

    本文主要介紹了Element?table?上下移需求的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-07-07
  • vue中setup語法糖寫法實例

    vue中setup語法糖寫法實例

    如果你在 vue3 開發(fā)中使用了語法的話,對于組件的name屬性,需要做一番額外的處理,下面這篇文章主要給大家介紹了關于Vue3 setup語法糖的相關資料,需要的朋友可以參考下
    2022-12-12
  • 解決vue打包css文件中背景圖片的路徑問題

    解決vue打包css文件中背景圖片的路徑問題

    今天小編就為大家分享一篇解決vue打包css文件中背景圖片的路徑問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • vue移動端路由切換實例分析

    vue移動端路由切換實例分析

    本篇文章給大家分享了vue移動端路由切換實例以及相關知識點,對此有興趣的朋友可以參考學習下。
    2018-05-05
  • vue-cli 3.x 配置Axios(proxyTable)跨域代理方法

    vue-cli 3.x 配置Axios(proxyTable)跨域代理方法

    今天小編就為大家分享一篇vue-cli 3.x 配置Axios(proxyTable)跨域代理方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-09-09
  • 詳細介紹解決vue和jsp結合的方法

    詳細介紹解決vue和jsp結合的方法

    這篇文章主要介紹了詳細介紹解決vue和jsp結合的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-02-02
  • vue如何通過事件的形式調用全局組件

    vue如何通過事件的形式調用全局組件

    這篇文章主要介紹了vue如何通過事件的形式調用全局組件問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-09-09
  • element-ui中樣式覆蓋問題的方法總結

    element-ui中樣式覆蓋問題的方法總結

    我們在使用element-ui的時候經常會遇到需要修改組件默認樣式,下面這篇文章主要給大家介紹了關于element-ui中樣式覆蓋問題的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • vue生成token并保存到本地存儲中

    vue生成token并保存到本地存儲中

    這篇文章主要介紹了vue生成token并保存到本地存儲中,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下
    2018-07-07

最新評論

兴和县| 浏阳市| 勃利县| 黄梅县| 上饶市| 曲阜市| 长寿区| 义马市| 磐安县| 广德县| 铜梁县| 临武县| 昌邑市| 裕民县| 得荣县| 台北县| 丹巴县| 延庆县| 城固县| 武胜县| 青岛市| 广州市| 仙游县| 天祝| 汶川县| 射洪县| 东源县| 浑源县| 夏邑县| 阿坝| 洞口县| 海晏县| 济南市| 保亭| 镇赉县| 永春县| 新丰县| 白水县| 大化| 陕西省| 灵川县|