以前寫了一篇 MultiPicker -『爲移動端而生』的自定義多級聯動選擇器,獲得了不少人的關注。鑑於不少人對這種手寫插件的過程很好奇,因此寫了幾篇文章,來講說它的成長史~git
在閱讀本文以前,確保你有稍微看過 MultiPicker 的源碼 喔~github
點擊查看源碼 ,也能夠在 npm 上找到他們:算法
回顧上集:如何造一個移動端的聯動選擇器(一)segmentfault
實現彈層的思路:【插入DOM → 初始化聯動的數據 → 綁定事件 】數組
① 在插入DOM的部分( initDomFuc ),採用字符串拼接的方式插入DOM(而不是使用字符串模板)。框架
聯動的主要結構式以下圖:dom
每一個聯動是一個 div,div 包裹着一個 ul,ul 中的每一個 li 就是聯動的值函數
其中div的高度是5個 li 的高度,ul的高度是實際的全部 li 的高度。
② 在初始化聯動數據的部分( initReady ),在頭尾分別插入兩個空字符,可以起到佔位符的做用,這樣在計算手勢的translate3d的時候更方便。
③ 爲DOM元素綁定事件時,具體作法有兩步:
第一步:爲每一個初始化好的ul綁定touch事件( initReady );
第二步:爲一些操做按鈕綁定事件( initBinding )。
③ - 第一步:touch事件的種類無非就是 touchstart、touchmove 和 touchend。但須要在每次滑動的時候記錄一些數據。這是爲了實現一個滑動加速度的效果,下文會說到。
③ - 第二步:用到了本身封裝的一個簡單的事件監聽函數on:
這個函數主要用在【觸發】【取消】和【提交】這幾個重要按鈕上。
PS:在設計樣式的過程當中考慮到,完整使用【年月日時分】
五種時間單位的場景居多,爲了優化界面和用戶體驗,因此在日期選擇器的設計中,須要設計一種帶tab切換
效果的完整版日期選擇器。其餘場景中不會出現。
我發現,不管用戶使用哪一個手指,只要用戶的滑動弧長在短期內比較大的話,說明用戶比較想快速向上滑或是向下滑。好比,在選擇出生年份的時候,用戶確定會想快速滑到上面的部分,就會用很快速的手勢向下滑動一個比較大的弧長。這時候就應該有一個滑動加速度的效果。
那麼如何實現呢,如何判斷用戶想要快速滑動呢?
很簡單,只須要考慮,單位時間內的速度變化率,也就是加速度,就好了。
以前提到過,在touchmove的過程當中會有一個 【speed數組】用來存儲滑動時,手勢的速度。
並在touchend中調用 initSpeed 函數,肯定最後 transition-duration
的值。
initSpeed 的主要工做是計算 speed 中的速度方差,方差和加速度是成正相關的。
因此當方差大於0.1時,ul 的實際滑動距離是手勢滑動距離的兩倍,transition-duration的值爲0.2s;
而當方差小於0.1的時候,就認爲基本是勻速滑動,ul 的實際滑動距等於手勢滑動距離,取 speed[0] 做爲 transition-duration 的值。
肯定好了滑動距離以後,就能夠計算最後停留的位置 translate3d ( initPosition )。
滑動加速度的效果就基本實現了。
Github地址:『爲移動端而生』的自定義多級聯動選擇器
到此,dom的操做和手勢算法就已經基本掌握了。
預知後話,後兩天見分曉
我是嘉寶Appian,一個賣萌出家的算法妹紙。