成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

學(xué)習(xí)移動(dòng)端組件 Picker一下

iOS122 / 3064人閱讀

摘要:原文前言一個(gè)移動(dòng)端的事件或者事件,具體看看怎么玩。初始化組件已經(jīng)有了基本的組件,現(xiàn)在我們開(kāi)始進(jìn)行一個(gè)初始化。因?yàn)槲覀兊谝粋€(gè)元素需要向下移動(dòng)一列,所以第一列應(yīng)該是空的這個(gè)時(shí)候位置也是我們位移最大位置??磮D最后目前只是一個(gè)最基本的例子。

原文: https://www.luoyangfu.com/art...
前言

一個(gè)移動(dòng)端的touch 事件或者 mouse 事件,具體看看怎么玩。

先看看效果:

這里年月日都是使用創(chuàng)建好的Picker組件來(lái)實(shí)現(xiàn)的,在之前感謝博客園 @糊糊糊糊糊了, 原文地址.

原文中講了實(shí)現(xiàn)Picker核心思路,我也是受益頗多,然后根據(jù)思路以及Github源碼,終于寫(xiě)了自己想要的Picker,于是就有了記錄,再次感謝.

多帶帶Picker HTML 結(jié)構(gòu)

開(kāi)發(fā)這個(gè)Picker, 觀(guān)察Picker節(jié)點(diǎn)結(jié)構(gòu),Picker 是由定高隱藏元素的塊, 一個(gè)定高不隱藏元素的的塊,以及一個(gè)選擇列表組成這三個(gè)部分。我們得知了這個(gè)Picker組成后很容易就可以寫(xiě)出來(lái)下面HTML的結(jié)構(gòu):

2016
2017
2018
2019
2020

這個(gè)就是最簡(jiǎn)單的 picker 結(jié)構(gòu)了。

CSS 樣式

咱們給這塊結(jié)構(gòu)添加樣式,顯示如下, 在這里我們默認(rèn)元素的高度在css 中寫(xiě)死為 50px.

我們這里就寫(xiě)了關(guān)于 Picker 基礎(chǔ)樣式。

.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;
}

上面僅僅僅僅包含圖片樣式組成,后續(xù)會(huì)逐漸添加各種樣式。

初始化Picker組件

已經(jīng)有了基本的 Picker 組件,現(xiàn)在我們開(kāi)始進(jìn)行一個(gè)初始化。讓第一個(gè)元素顯示在正確的位置。
這里有兩個(gè)基本問(wèn)題需要先考慮一下:

元素的移動(dòng)范圍

元素的下標(biāo)和位置交換

元素的移動(dòng)范圍

我們?cè)匾苿?dòng)范圍用下標(biāo)來(lái)說(shuō)的話(huà),應(yīng)該是 1 到 length, 這里length 就是傳入Picker數(shù)據(jù)長(zhǎng)度。

因?yàn)槲覀兊谝粋€(gè)元素需要向下移動(dòng)一列,所以第一列應(yīng)該是空的, 這個(gè)時(shí)候位置也是我們位移最大位置。當(dāng)不斷將Picker 向上位移什么時(shí)候?yàn)樽钚〉奈恢媚???yīng)該是有這樣計(jì)算 (length - Math.ceil(count / 2)) * 50. 這里我們說(shuō)的是顯示3列情況, length 為數(shù)據(jù)長(zhǎng)度, 50為單個(gè)Picker高度,上文已有。

下面直接看元素結(jié)算范圍:

const getMoveRange = function() {
  const max = Math.floor(visibleCount / 2) * itemHeight;
  const min = (itemLength - Math.ceil(visibleCount / 2)) * -itemHeight;
  return [min, max]
}

這里就解決了第一個(gè)元素的范圍問(wèn)題。

這里使用兩個(gè)數(shù)學(xué)函數(shù):
Math.floor 取不大于該數(shù)的最大整數(shù)
Math.ceil 取不小于該數(shù)的最小整數(shù)
元素的下標(biāo)和位置交換

這里需要兩個(gè)函數(shù)分別來(lái)計(jì)算使用下標(biāo)獲取位置,使用位置來(lái)獲取下標(biāo)的。

通過(guò)下標(biāo)獲取元素位置時(shí)候有一點(diǎn)需要注意的是,我們?cè)匚恢檬切枰鶕?jù)當(dāng)前顯示的個(gè)數(shù)進(jìn)行偏移的,也就說(shuō),在計(jì)算之前,需要減去偏移量。偏移量剛好等于 Math.floor(count / 2)。

const getTranslByIndex = function(index) {
  const offset = Math.floor(visibleCount / 2)
  
  if(index >= 0) {
    return (index - offset) * -itemHeight
  }
}

通過(guò)位移獲取元素位置就簡(jiǎn)單很多了。

const getIndexByTransl = function(transl) {
  transl = Math.round(transl / itemHeight) * itemHeight;
  const index = - (transl - Math.floor(visibleCount / 2) * itemHeight) / itemHeight;
  
  return index;
}

計(jì)算用了三行代碼, 第一行主要是轉(zhuǎn)化當(dāng)前位置靠近哪一個(gè)元素,得到具體translate,第二行 計(jì)算具體的 index, 這里計(jì)算語(yǔ)句前面使用 -減號(hào), 主要因?yàn)?translate 減去顯示個(gè)數(shù)的1/2后,總是負(fù)值,這里需要將負(fù)值轉(zhuǎn)正,也可以使用 Math.abs 來(lái)替代。

上面我們就解決了兩個(gè)問(wèn)題。

初始化組件

首先需要組件初始化為上圖的樣子,這個(gè)時(shí)候,我們開(kāi)始監(jiān)聽(tīng)事件,這了我們主要監(jiān)聽(tīng) 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 元素集合.

這里就對(duì)元素進(jìn)行了touchstart,touchmove, touchend 監(jiān)聽(tīng)。下面我進(jìn)一步對(duì)事件做處理,讓picker動(dòng)起來(lái)。
為了讓picker 在移動(dòng)過(guò)程中有過(guò)度效果,增加如下css

.picker-wrapper {
    overflow: visible;
    height: calc(50px * 3);
    transition: all 0.3s ease-in-out; /* 這里就對(duì) 元素做了過(guò)渡動(dòng)畫(huà)處理*/
}

開(kāi)始對(duì)事件進(jìn)行處理

el.addEventListener("touchstart", function(e) {
    startAt = Date.now();
    startTop = e.touches[0].pageY;
    // 開(kāi)始滾動(dòng)的位置
    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 就開(kāi)始彈性滾動(dòng)
    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);
  });

  // 每個(gè)item 點(diǎn)擊生效
  Array.prototype.forEach.call(pickerItems, function(item, index) {
    item.addEventListener("click", function(e) {
      setSelectedEl(index);
      translateY = getTranslByIndex(index);
      translateEl();
    });
  });

這里就對(duì)觸摸事件做了處理,也對(duì)單個(gè)元素的點(diǎn)擊做了監(jiān)聽(tīng)。

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;
// 動(dòng)力參數(shù)
let momentumRatio = 7;
// 速度速度位移
let velocityTranslate = 0;

這里再開(kāi)頭申明了一些內(nèi)容,主要說(shuō)明一下 momentumRatiovelocityTranslate 這兩個(gè),前者是動(dòng)力系數(shù)用于短時(shí)間修改位移后慣性移動(dòng),后者是速度位移用于在用戶(hù)移動(dòng)過(guò)程中移動(dòng)的量。

現(xiàn)在就完成了一個(gè)基本的Picker。看圖:

最后

目前只是一個(gè)最基本的例子。如果說(shuō)需要選擇兩側(cè)有一個(gè)縮放呢。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/105269.html

相關(guān)文章

  • 記 vue 移動(dòng)開(kāi)發(fā) 中的經(jīng)驗(yàn)(2)

    摘要:官網(wǎng)還不斷的訪(fǎng)問(wèn)不了。在此推薦一個(gè)移動(dòng)端庫(kù)按需引入二次封裝組件列表的下拉刷新和上拉加載更多是移動(dòng)端必須的組件。不用寫(xiě)死高度了,并且兼容對(duì)外提供了更加簡(jiǎn)明易用的刷新,回到頂部,獲得和設(shè)置滾動(dòng)條位置的方法統(tǒng)一的提示,免去重復(fù)代碼。 按需引入mint-ui 本項(xiàng)目用了 mint-ui 作為基礎(chǔ)ui框架,在使用中遇到不少問(wèn)題。官網(wǎng)doc 還不斷的訪(fǎng)問(wèn)不了。不過(guò)還是很感謝 mint-ui 團(tuán)隊(duì)。...

    Flands 評(píng)論0 收藏0
  • 地區(qū)picker 各選擇器,優(yōu)劣分析

    摘要:移動(dòng)端選擇器有很多,各大組件都有自己的,比如,,,等等。這次的地區(qū)選擇,需要地區(qū)的省份市經(jīng)緯度,還要設(shè)置第一次點(diǎn)開(kāi)的時(shí)候是特定城市。引入樣式和文件地區(qū)選擇級(jí)聯(lián)地區(qū)選擇設(shè)定默認(rèn)選項(xiàng)省份城市代碼很簡(jiǎn)單,不懂的百度一下。移動(dòng)端選擇器picker有很多,各大ui組件都有自己的picker,比如light7,HUI,MUI,jqueryUI等等。但是,我發(fā)現(xiàn)他們都有各種各樣的問(wèn)題。這次的地區(qū)選擇,需要...

    番茄西紅柿 評(píng)論0 收藏0
  • 基于 vue 的 picker 組件 vue-awesome-picker

    摘要:本組件停止維護(hù)組件庫(kù)請(qǐng)移步小程序組件庫(kù)請(qǐng)移步有贊前端大量坑位,內(nèi)推私信基于的移動(dòng)端組件支持單列多列和聯(lián)級(jí)數(shù)據(jù)內(nèi)置時(shí)間日期數(shù)據(jù)滾輪效果顏色可配置已啟用試試離線(xiàn)訪(fǎng)問(wèn)吧點(diǎn)擊查看詳細(xì)使用方法參照源碼參數(shù)描述可選類(lèi)型默認(rèn)詳細(xì)描述 ?? DEPRECATED 本組件停止維護(hù) ?? Vue 組件庫(kù)請(qǐng)移步 Vant ?? 小程序組件庫(kù)請(qǐng)移步 Vant Weapp ?? 有贊前端大量坑位,內(nèi)推私信 v...

    Lsnsh 評(píng)論0 收藏0
  • UI組件庫(kù)從1到N開(kāi)發(fā)心得-組件

    摘要:正文距離第一篇組件庫(kù)文章發(fā)布已經(jīng)過(guò)去個(gè)月了,在此期間利用零零散散的時(shí)間持續(xù)更新組件庫(kù),目前移動(dòng)端組件庫(kù)已經(jīng)更新大類(lèi)基礎(chǔ)表單彈出層種組件供使用。鏈接組件庫(kù)從到開(kāi)發(fā)心得主頁(yè)更改版版方案祝工作順利鄧文斌年月日正文 距離第一篇UI組件庫(kù)文章發(fā)布已經(jīng)過(guò)去3個(gè)月了,在此期間利用零零散散的時(shí)間持續(xù)更新owl-ui組件庫(kù),目前owl-ui移動(dòng)端組件庫(kù)已經(jīng)更新3大類(lèi)(基礎(chǔ)、表單、彈出層)9種組件(Button...

    hzc 評(píng)論0 收藏0
  • 基于zepto的移動(dòng)輕量級(jí)日期插件

    摘要:本文簡(jiǎn)單介紹近來(lái)寫(xiě)的一款基于的移動(dòng)端輕量級(jí)日期插件。再來(lái)看看兼容性對(duì)于移動(dòng)開(kāi)發(fā)足矣最后就是在綁定事件的兼容性問(wèn)題,不同廠(chǎng)商對(duì)于這個(gè)事件的定義并不一致,比如里面監(jiān)聽(tīng)的是事件,但是在安卓里面監(jiān)聽(tīng)事件完全沒(méi)反應(yīng),經(jīng)過(guò)一番,發(fā)現(xiàn)安卓需要監(jiān)聽(tīng)事件。 前言 做過(guò)移動(dòng)Web開(kāi)發(fā)的同學(xué)都知道,移動(dòng)端日期選擇是很常見(jiàn)的需求。在PC端,我們有很豐富的選擇,比較出名的就有Mobiscroll和jQuery ...

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

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

0條評(píng)論

閱讀需要支付1元查看
<