成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

匠心打造Vue側(cè)滑菜單組件

張漢慶 / 1749人閱讀

摘要:本文介紹一個(gè)簡(jiǎn)單的類似的布局組件的實(shí)現(xiàn),基于。介紹的內(nèi)容已經(jīng)制作成組件。即當(dāng)不可以拖出抽屜時(shí),應(yīng)觸發(fā)默認(rèn)事件,比如垂直方向的滾動(dòng)等等。這種優(yōu)化可以將一部分復(fù)雜的計(jì)算工作提前準(zhǔn)備好,使頁(yè)面的反應(yīng)更為快速靈敏。

本文介紹一個(gè)簡(jiǎn)單的DrawerLayout(類似Android的DrawerLayout)布局組件的實(shí)現(xiàn),基于Vue.js。介紹的內(nèi)容已經(jīng)制作成 vue-drawer-layout 組件。
前言

大家有興趣先用手機(jī)掃一掃這個(gè)二維碼,或者點(diǎn)我

然后點(diǎn)擊頁(yè)面中左上角的頭像打開(kāi)drawer或者向右向左拖拽,就可以看到下面gif的效果,打開(kāi)自己的手機(jī)QQ,是不是很像:)

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

HTML結(jié)構(gòu)

頁(yè)面結(jié)構(gòu)很簡(jiǎn)單,一個(gè)抽屜,一個(gè)主容器,內(nèi)容可以利用slot支持外部自行定制。

抽屜一開(kāi)始是隱藏在左側(cè)屏幕外的,故設(shè)置left:-100%使其整個(gè)都藏在外部

使用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坐標(biāo)記為startX,滑動(dòng)中手指的位置x坐標(biāo)記為nowX,drawer的x坐標(biāo)偏移量記為startPos

let startX, nowX, startPos;

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

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; //滑動(dòng)中手指的位置x坐標(biāo)
    let pos = startPos + nowX - startX; 
    pos = Math.min(width, pos); //不能超過(guò)滑動(dòng)最大值
    pos = Math.max(0, pos); //不能小于0
    this.pos = pos; //設(shè)置滾動(dòng)距離為拖動(dòng)的距離
}.bind(this);

那么,手指滑動(dòng)的距離就是nowX - startX,當(dāng)前drawer的位置為startPos + nowX - startX,這樣抽屜已經(jīng)跟隨手指向右移動(dòng)了,并且不會(huì)超過(guò)我們?cè)O(shè)置的拖動(dòng)最大值。

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

接下來(lái)你會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,當(dāng)手指垂直滾動(dòng)主內(nèi)容時(shí),向右滑動(dòng)手指也會(huì)拖出抽屜,這時(shí)應(yīng)該做一件事:區(qū)分垂直滑動(dòng)和水平滑動(dòng)

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

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

當(dāng)手指按下觸發(fā)touchstart時(shí),記錄初始位置P0;當(dāng)滑動(dòng)手指時(shí),觸發(fā)的第一次touchmove時(shí),記錄位置P1,我們將P0到P1的矢量記為S(原諒我這個(gè)靈魂畫手)

這時(shí)候很容易看出,∠θ大于某個(gè)值時(shí),比如30度,就可能是垂直方向的滾動(dòng)操作而不是拖動(dòng)抽屜。所以,可以根據(jù)y/x>tan30°得到判斷條件:

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

當(dāng)isVerticletrue時(shí),不執(zhí)行drawer的拖動(dòng)

讓Drawer動(dòng)起來(lái)

我們使用css3的transition屬性使drawer具有過(guò)渡動(dòng)畫效果,這里寫一個(gè)moving

.moving
    transition transform .3s ease

別忘了加上class綁定,拖動(dòng)時(shí)是不需要過(guò)渡動(dòng)畫的(要跟隨手指),而松開(kāi)手指時(shí)才需要過(guò)渡動(dòng)畫。

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

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

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

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

其實(shí)是我們?cè)?b>touchstart可以預(yù)先告知瀏覽器抽屜可能要發(fā)生位移

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

當(dāng)然最后別忘了在transitionend事件后把transitionwill-change去掉,讓瀏覽器歇一會(huì)兒~

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

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

咦?passive是什么鬼?

網(wǎng)站使用被動(dòng)事件偵聽(tīng)器以提升滾動(dòng)性能,在您的觸摸和滾輪事件偵聽(tīng)器上設(shè)置 passive 選項(xiàng)可提升滾動(dòng)性能 具體看這里

原來(lái)這是現(xiàn)代瀏覽器的一個(gè)新特性,我們需要以新的方式來(lái)綁定我們的touch事件,當(dāng)然首先先檢測(cè)一下是否支持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);

是否有效果呢?有興趣的朋友可以點(diǎn)這里看國(guó)外大神的視頻

寫在最后

本文介紹了實(shí)現(xiàn)抽屜式導(dǎo)航欄的主要過(guò)程,詳細(xì)代碼已封裝成vue-drawer-layout組件,支持更豐富的定制和使用方式,具體文檔可以訪問(wèn)我的github或者npm官網(wǎng)檢索。歡迎各位多多提issue,不吝賜教,感謝!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/112911.html

相關(guān)文章

  • 匠心打造Vue側(cè)滑菜單組件

    摘要:本文介紹一個(gè)簡(jiǎn)單的類似的布局組件的實(shí)現(xiàn),基于。介紹的內(nèi)容已經(jīng)制作成組件。即當(dāng)不可以拖出抽屜時(shí),應(yīng)觸發(fā)默認(rèn)事件,比如垂直方向的滾動(dòng)等等。這種優(yōu)化可以將一部分復(fù)雜的計(jì)算工作提前準(zhǔn)備好,使頁(yè)面的反應(yīng)更為快速靈敏。 本文介紹一個(gè)簡(jiǎn)單的DrawerLayout(類似Android的DrawerLayout)布局組件的實(shí)現(xiàn),基于Vue.js。介紹的內(nèi)容已經(jīng)制作成 vue-drawer-layout...

    sutaking 評(píng)論0 收藏0
  • vue移動(dòng)端側(cè)滑面板組件

    摘要:里邊涉及到的指令是自定義的指令,為了處理移動(dòng)端的點(diǎn)擊操作,我還整理了一片陋文移動(dòng)點(diǎn)擊長(zhǎng)按滑動(dòng)指令然后這個(gè)組件的源碼我放在了我出來(lái)的項(xiàng)目上謝謝各位品嘗, 以下這段都是廢話,請(qǐng)?zhí)^(guò) 公司移動(dòng)端開(kāi)發(fā)平臺(tái)進(jìn)行了大變革,前端架構(gòu)由DCloud大生態(tài)轉(zhuǎn)換為VUE,所以移動(dòng)端的UI組件庫(kù)從MUI改為使用MintUI,然后開(kāi)始大刀闊斧的把MintUI組件改成MUI組件的樣子,然后發(fā)現(xiàn)少了幾個(gè)較為常用的...

    TNFE 評(píng)論0 收藏0
  • 匠心打造canvas簽名組件

    摘要:原文匠心打造簽名組件導(dǎo)讀月又是項(xiàng)目吃緊的時(shí)候,一大波需求襲來(lái),猝不及防。可以先戳這里體驗(yàn)把后面將要提到的簽名組件。剩下的也是綁定事件中關(guān)鍵的一步。設(shè)置完成了上述功能,一個(gè)簽名插件就已經(jīng)成型了。 本文首發(fā)于CSDN網(wǎng)站,下面的版本又經(jīng)過(guò)進(jìn)一步的修訂。原文:匠心打造canvas簽名組件 導(dǎo)讀 6月又是項(xiàng)目吃緊的時(shí)候,一大波需求襲來(lái),猝不及防。 度過(guò)了漫長(zhǎng)而煎熬的6月,是時(shí)候總結(jié)一波。最近移...

    MAX_zuo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<