摘要:原文前言一個移動端的事件或者事件,具體看看怎么玩。初始化組件已經有了基本的組件,現在我們開始進行一個初始化。因為我們第一個元素需要向下移動一列,所以第一列應該是空的這個時候位置也是我們位移最大位置。看圖最后目前只是一個最基本的例子。
原文: https://www.luoyangfu.com/art...前言
一個移動端的touch 事件或者 mouse 事件,具體看看怎么玩。
先看看效果:
這里年月日都是使用創建好的Picker組件來實現的,在之前感謝博客園 @糊糊糊糊糊了, 原文地址.
原文中講了實現Picker核心思路,我也是受益頗多,然后根據思路以及Github源碼,終于寫了自己想要的Picker,于是就有了記錄,再次感謝.
多帶帶Picker HTML 結構開發這個Picker, 觀察Picker節點結構,Picker 是由定高隱藏元素的塊, 一個定高不隱藏元素的的塊,以及一個選擇列表組成這三個部分。我們得知了這個Picker組成后很容易就可以寫出來下面HTML的結構:
20162017201820192020
這個就是最簡單的 picker 結構了。
CSS 樣式咱們給這塊結構添加樣式,顯示如下, 在這里我們默認元素的高度在css 中寫死為 50px.
我們這里就寫了關于 Picker 基礎樣式。
.picker { overflow: hidden; position: relative; z-index: 1; } .picker-wrapper { overflow: visible; height: calc(50px * 3); } .picker-item { height: 50px; line-height: 50px; text-align: center; color: #999; } .picker-item.active { color: #000; } .picker-center-highlight { height: 50px; position: absolute; width: 100%; top: 50%; margin-top: -25px; z-index: 2; } .picker-center-highlight::before, .picker-center-highlight::after { content: ""; display: block; height: 2px; background-color: #000; width: 100%; transform: scaleY(0.5); position: absolute; } .picker-center-highlight::before { top: 0; } .picker-center-highlight::after { bottom: 0; }
上面僅僅僅僅包含圖片樣式組成,后續會逐漸添加各種樣式。
初始化Picker組件已經有了基本的 Picker 組件,現在我們開始進行一個初始化。讓第一個元素顯示在正確的位置。
這里有兩個基本問題需要先考慮一下:
元素的移動范圍
元素的下標和位置交換
元素的移動范圍我們元素移動范圍用下標來說的話,應該是 1 到 length, 這里length 就是傳入Picker數據長度。
因為我們第一個元素需要向下移動一列,所以第一列應該是空的, 這個時候位置也是我們位移最大位置。當不斷將Picker 向上位移什么時候為最小的位置呢?應該是有這樣計算 (length - Math.ceil(count / 2)) * 50. 這里我們說的是顯示3列情況, length 為數據長度, 50為單個Picker高度,上文已有。
下面直接看元素結算范圍:
const getMoveRange = function() { const max = Math.floor(visibleCount / 2) * itemHeight; const min = (itemLength - Math.ceil(visibleCount / 2)) * -itemHeight; return [min, max] }
這里就解決了第一個元素的范圍問題。
這里使用兩個數學函數:元素的下標和位置交換
Math.floor 取不大于該數的最大整數
Math.ceil 取不小于該數的最小整數
這里需要兩個函數分別來計算使用下標獲取位置,使用位置來獲取下標的。
通過下標獲取元素位置時候有一點需要注意的是,我們元素位置是需要根據當前顯示的個數進行偏移的,也就說,在計算之前,需要減去偏移量。偏移量剛好等于 Math.floor(count / 2)。
const getTranslByIndex = function(index) { const offset = Math.floor(visibleCount / 2) if(index >= 0) { return (index - offset) * -itemHeight } }
通過位移獲取元素位置就簡單很多了。
const getIndexByTransl = function(transl) { transl = Math.round(transl / itemHeight) * itemHeight; const index = - (transl - Math.floor(visibleCount / 2) * itemHeight) / itemHeight; return index; }
計算用了三行代碼, 第一行主要是轉化當前位置靠近哪一個元素,得到具體translate,第二行 計算具體的 index, 這里計算語句前面使用 -減號, 主要因為 translate 減去顯示個數的1/2后,總是負值,這里需要將負值轉正,也可以使用 Math.abs 來替代。
上面我們就解決了兩個問題。
初始化組件首先需要組件初始化為上圖的樣子,這個時候,我們開始監聽事件,這了我們主要監聽 touchstart, touchmove, touchend 事件。
const translateEl = function(transl) { el.style.transform = `translateY(${transl}px)`; }; const setSelectedEl = function(index) { Array.prototype.forEach.call(pickerItems, (item, idx) => { item.classList.remove("active"); }); pickerItems[index].classList.add("active"); }; function initEvent() { el.addEventListener("touchstart", function(e) { console.log("touchstart", e); }); el.addEventListener("touchmove", function(e) { console.log("touchmove", e); }); el.addEventListener("touchend", function(e) { console.log("touchenv", e); }); } window.onload = function onload() { translateY = getTranslByIndex(0); setSelectedEl(0); translateEl(); initEvent(); };
上面的 pickerItems 就是選中的picker 元素集合.
這里就對元素進行了touchstart,touchmove, touchend 監聽。下面我進一步對事件做處理,讓picker動起來。
為了讓picker 在移動過程中有過度效果,增加如下css
.picker-wrapper { overflow: visible; height: calc(50px * 3); transition: all 0.3s ease-in-out; /* 這里就對 元素做了過渡動畫處理*/ }
開始對事件進行處理
el.addEventListener("touchstart", function(e) { startAt = Date.now(); startTop = e.touches[0].pageY; // 開始滾動的位置 startTranslateY = translateY; }); el.addEventListener("touchmove", function(e) { const deltaY = e.touches[0].pageY - startTop; translateY = startTranslateY + deltaY; velocityTranslate = translateY - prevTranslateY || translateY; prevTranslateY = translateY; translateEl(); }); el.addEventListener("touchend", function(e) { let momentumTranslate = 0; // 小于 300 就開始彈性滾動 if (Date.now() - startAt < 300) { momentumTranslate = translateY + velocityTranslate * momentumRatio; } let translate = Math.round(translateY / itemHeight) * itemHeight; if (momentumTranslate) { translate = Math.round(momentumTranslate / itemHeight) * itemHeight; } const range = getMoveRange(); translateY = Math.max(Math.min(translate, range[1]), range[0]); translateEl(); const index = getIndexByTransl(translateY); setSelectedEl(index); }); // 每個item 點擊生效 Array.prototype.forEach.call(pickerItems, function(item, index) { item.addEventListener("click", function(e) { setSelectedEl(index); translateY = getTranslByIndex(index); translateEl(); }); });
這里就對觸摸事件做了處理,也對單個元素的點擊做了監聽。
const el = document.querySelector("#wrapper"); const itemHeight = 50; const visibleCount = 3; const itemLength = 5; const pickerItems = document.querySelectorAll(".picker-item"); let startAt = Date.now(); let startTop = 0; let translateY = 0; let startTranslateY = 0; let prevTranslateY = 0; // 動力參數 let momentumRatio = 7; // 速度速度位移 let velocityTranslate = 0;
這里再開頭申明了一些內容,主要說明一下 momentumRatio 和 velocityTranslate 這兩個,前者是動力系數用于短時間修改位移后慣性移動,后者是速度位移用于在用戶移動過程中移動的量。
現在就完成了一個基本的Picker。看圖:
最后目前只是一個最基本的例子。如果說需要選擇兩側有一個縮放呢。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/105269.html
摘要:官網還不斷的訪問不了。在此推薦一個移動端庫按需引入二次封裝組件列表的下拉刷新和上拉加載更多是移動端必須的組件。不用寫死高度了,并且兼容對外提供了更加簡明易用的刷新,回到頂部,獲得和設置滾動條位置的方法統一的提示,免去重復代碼。 按需引入mint-ui 本項目用了 mint-ui 作為基礎ui框架,在使用中遇到不少問題。官網doc 還不斷的訪問不了。不過還是很感謝 mint-ui 團隊。...
摘要:移動端選擇器有很多,各大組件都有自己的,比如,,,等等。這次的地區選擇,需要地區的省份市經緯度,還要設置第一次點開的時候是特定城市。引入樣式和文件地區選擇級聯地區選擇設定默認選項省份城市代碼很簡單,不懂的百度一下。移動端選擇器picker有很多,各大ui組件都有自己的picker,比如light7,HUI,MUI,jqueryUI等等。但是,我發現他們都有各種各樣的問題。這次的地區選擇,需要...
摘要:本組件停止維護組件庫請移步小程序組件庫請移步有贊前端大量坑位,內推私信基于的移動端組件支持單列多列和聯級數據內置時間日期數據滾輪效果顏色可配置已啟用試試離線訪問吧點擊查看詳細使用方法參照源碼參數描述可選類型默認詳細描述 ?? DEPRECATED 本組件停止維護 ?? Vue 組件庫請移步 Vant ?? 小程序組件庫請移步 Vant Weapp ?? 有贊前端大量坑位,內推私信 v...
摘要:正文距離第一篇組件庫文章發布已經過去個月了,在此期間利用零零散散的時間持續更新組件庫,目前移動端組件庫已經更新大類基礎表單彈出層種組件供使用。鏈接組件庫從到開發心得主頁更改版版方案祝工作順利鄧文斌年月日正文 距離第一篇UI組件庫文章發布已經過去3個月了,在此期間利用零零散散的時間持續更新owl-ui組件庫,目前owl-ui移動端組件庫已經更新3大類(基礎、表單、彈出層)9種組件(Button...
摘要:本文簡單介紹近來寫的一款基于的移動端輕量級日期插件。再來看看兼容性對于移動開發足矣最后就是在綁定事件的兼容性問題,不同廠商對于這個事件的定義并不一致,比如里面監聽的是事件,但是在安卓里面監聽事件完全沒反應,經過一番,發現安卓需要監聽事件。 前言 做過移動Web開發的同學都知道,移動端日期選擇是很常見的需求。在PC端,我們有很豐富的選擇,比較出名的就有Mobiscroll和jQuery ...
閱讀 2574·2021-11-18 10:02
閱讀 1713·2021-09-30 10:00
閱讀 5310·2021-09-22 15:27
閱讀 1204·2019-08-30 15:54
閱讀 3671·2019-08-29 11:13
閱讀 2945·2019-08-29 11:05
閱讀 3319·2019-08-29 11:01
閱讀 569·2019-08-26 13:52