基于uni-app開發(fā)刻度尺組件的實(shí)現(xiàn)示例
一、前言
小編最近接到一個(gè)任務(wù),就是在輸入數(shù)值的時(shí)候不再使用傳統(tǒng)的鍵盤了,而是用拖拉尺子的形式選擇數(shù)值,大概長(zhǎng)這樣:
其實(shí)這需求不是第一次提出來(lái)了,在我們的應(yīng)用第一版的時(shí)候產(chǎn)品就想這樣做。
當(dāng)然小編我當(dāng)時(shí)剛接到這個(gè)任務(wù)的時(shí)候是拒絕的,你不能讓我做,我就馬上去做,第一我要調(diào)研一下,因?yàn)槲也幌牖敲炊鄷r(shí)間成本開發(fā)出這個(gè)組件再加一些特技上去,
滑動(dòng)超過邊緣還能duang一下彈回來(lái),但是其實(shí)用起來(lái)還沒直接鍵盤輸入數(shù)字來(lái)得方便,這樣領(lǐng)導(dǎo)出來(lái)一定會(huì)罵我;后面經(jīng)過一番調(diào)研和時(shí)間評(píng)估,最終選擇了另一套方案:
自己寫了一套數(shù)字鍵盤,比刻度尺簡(jiǎn)單很多,也不怎么耗性能,用起來(lái)還挺方便。
為什么不用系統(tǒng)自帶鍵盤呢?這個(gè)不用說(shuō),大家都知道手機(jī)瀏覽器調(diào)用系統(tǒng)自帶鍵盤有多惡心。
然而,該應(yīng)用迎來(lái)了第二個(gè)版本,產(chǎn)品又把刻度尺拿了出來(lái)并揚(yáng)言:“要砍需求先砍我!”。
不過確實(shí),第二版有了更加復(fù)雜的場(chǎng)景,選擇的數(shù)值需要限制范圍,而且范圍大小會(huì)隨著一些條件不斷變化,要想用戶能直觀并快速地輸入正確的數(shù)值,只能是刻度尺了。
然后經(jīng)過小編兩分鐘的深思熟慮,最終把任務(wù)接了下來(lái)。
二、開發(fā)
首先我們來(lái)看看刻度尺有哪些特點(diǎn)。
- 可以滑動(dòng);
- 根據(jù)滑動(dòng)距離輸出數(shù)值;
- 滑過頭了會(huì)自動(dòng)回彈;
看起來(lái),我們可以基于uni-app提供的scroll-view組件來(lái)開發(fā),該組件有提供以下屬性正好適合我們的刻度尺特性:
屬性名 | 類型 | 默認(rèn)值 | 說(shuō)明 |
---|---|---|---|
scroll-x | Boolean | false | 允許橫向滾動(dòng) |
scroll-left | Number/String | 設(shè)置橫向滾動(dòng)條位置 | |
scroll-with-animation | Boolean | false | 在設(shè)置滾動(dòng)條位置時(shí)使用動(dòng)畫過渡 |
@scroll | EventHandle | 滾動(dòng)時(shí)觸發(fā),event.detail = {scrollLeft, scrollTop, scrollHeight, scrollWidth, deltaX, deltaY} |
然后第二步,需要計(jì)算刻度。
小編先設(shè)置好了默認(rèn)每個(gè)刻度占10像素;
const GUTTER = 10;
然后就開始計(jì)算我們一共需要多少個(gè)刻度,其實(shí)很簡(jiǎn)單,就是你需要多少刻度,就傳進(jìn)來(lái)一個(gè)最大最小值,然后用最大值減去最小值,就是刻度的數(shù)量了;
這時(shí)候會(huì)出現(xiàn)一個(gè)交互問題,因?yàn)榭潭瘸叩倪x擇標(biāo)是放在屏幕中間的,所以刻度尺的邊界是需要顯示多余的刻度用來(lái)充滿屏幕,于是小編就決定生成相當(dāng)于兩倍于屏幕寬度的多余刻度;
// 多余的刻度數(shù)量 const extraGridCount = Math.ceil(window.innerWidth / GUTTER); // 生成刻度數(shù)組 this.gridList = Array.from(Array(this.gridMax - this.gridMin + extraGridCount * 2)).map((_, i) => { const num = i + this.gridMin - extraGridCount; const displayNum = this.decimal === 1 ? num / 10 : num; return { num, displayNum, isLongGrid: num % GUTTER === 0, showText: num % GUTTER === 0 && num >= this.gridMin && num <= this.gridMax } });
刻度數(shù)組內(nèi)每個(gè)元素就是一個(gè)刻度對(duì)象,包含了以下屬性:
- 刻度數(shù)值
- 刻度顯示的數(shù)值(顯示的數(shù)值可能會(huì)與實(shí)際數(shù)值不一致,是為了擴(kuò)展小數(shù)用的)
- 是否是長(zhǎng)刻度(因?yàn)榭潭瘸呙扛?0個(gè)就會(huì)出現(xiàn)一條長(zhǎng)刻度)
- 是否顯示刻度的數(shù)值(只有長(zhǎng)刻度和有效刻度才會(huì)顯示數(shù)值)
數(shù)組生成好,就可以根據(jù)數(shù)組來(lái)渲染整個(gè)刻度尺了;
<u-row v-if="show" class="grid-wrapper" align="top"> <view class="grid-item" :class="{'long': item.isLongGrid}" v-for="(item, i) in gridList" :key="i" :style="item.showText ? { ...gridItemStyle, height: '40px' } : gridItemStyle" > <text class="grid-num" v-if="item.showText" >{{item.displayNum}}</text> </view> </u-row>
渲染完畢之后,就可以通過一些算法計(jì)算刻度尺的初始位置了。然后通過scroll事件,在刻度尺滑動(dòng)過程中計(jì)算數(shù)值;
scroll(e){ const scrollLeft = e.detail.scrollLeft; let value = Math.floor((scrollLeft - this.offsetScroll + this.gridMin * GUTTER) / GUTTER); if(value < this.gridMin){ value = this.gridMin; }else if(value > this.gridMax){ value = this.gridMax; }}
其中offsetScroll 就是多余的那部分刻度,需要減掉的,還要判斷一下是否小于最小值或者是否大于最大值; 接下來(lái)就是刻度尺的回彈了,當(dāng)滑動(dòng)超過最大值或最小值時(shí),需要往回彈,在視覺上與計(jì)算好的數(shù)值保持一致; 其實(shí)也只是在滑動(dòng)結(jié)束時(shí)算一下刻度尺是否應(yīng)該回到邊界就好了,動(dòng)畫上scroll-view已經(jīng)幫我們解決好了;
adjustScrollPosition(){ /** 滾動(dòng)結(jié)束后調(diào)節(jié)滾動(dòng)位置 */ if(this.actualScrollLeft < this.offsetScroll){ this.scrollLeft = this.offsetScroll + (Math.random() / 100); } else if(this.actualScrollLeft > (this.gridMax - this.gridMin) * GUTTER + this.offsetScroll){ this.scrollLeft = (this.gridMax - this.gridMin) * GUTTER + this.offsetScroll + (Math.random() / 100); } else if(Math.floor(this.actualScrollLeft - this.offsetScroll) % GUTTER !== 0){ const dryScrollLeft = this.actualScrollLeft - this.offsetScroll; this.scrollLeft = dryScrollLeft - dryScrollLeft % GUTTER + this.offsetScroll; } }
至此,一個(gè)刻度尺組件就大致完成了。當(dāng)然,還有很多細(xì)節(jié)問題沒解決,比如:
- 要是需要支持小數(shù)位怎么辦呢;
- 如果刻度過多是否有性能問題呢;
- 等等...
這些問題就由大家思考完善一下吧
到此這篇關(guān)于基于uni-app開發(fā)刻度尺組件的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)uni-app 刻度尺 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
在JavaScript中正確引用bind方法的應(yīng)用
本文的重點(diǎn)在于討論bind()方法的實(shí)現(xiàn),在開始討論bind()的實(shí)現(xiàn)之前,我們先來(lái)看看bind()方法的使用,有需要的小伙伴可以參考下。2015-05-05js實(shí)現(xiàn)的簡(jiǎn)單圖片浮動(dòng)效果完整實(shí)例
這篇文章主要介紹了js實(shí)現(xiàn)的簡(jiǎn)單圖片浮動(dòng)效果,以完整實(shí)例形式分析了javascript實(shí)現(xiàn)圖片定時(shí)漂浮移動(dòng)功能的方法,涉及javascript定時(shí)函數(shù)與數(shù)值動(dòng)態(tài)運(yùn)算相關(guān)技巧,需要的朋友可以參考下2016-05-05js中對(duì)函數(shù)設(shè)置默認(rèn)參數(shù)值的3種方法
這篇文章主要介紹了js中對(duì)函數(shù)設(shè)置默認(rèn)參數(shù)值的3種方法嗎,3種方法都具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-10-10淺析JavaScript中的同名標(biāo)識(shí)符優(yōu)先級(jí)
這篇文章主要介紹了JavaScript中的同名標(biāo)識(shí)符優(yōu)先級(jí)。需要的朋友可以過來(lái)參考下,希望對(duì)大家有所幫助2013-12-12JS運(yùn)動(dòng)特效之完美運(yùn)動(dòng)框架實(shí)例分析
這篇文章主要介紹了JS運(yùn)動(dòng)特效之完美運(yùn)動(dòng)框架,結(jié)合實(shí)例形式分析了javascript針對(duì)運(yùn)動(dòng)中的元素屬性檢測(cè)與判斷相關(guān)操作技巧,需要的朋友可以參考下2018-01-01小程序圖片長(zhǎng)按識(shí)別功能的實(shí)現(xiàn)方法
這篇文章主要介紹了小程序圖片長(zhǎng)按識(shí)別功能的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-08-08js如何調(diào)用qq互聯(lián)api實(shí)現(xiàn)第三方登錄
這篇文章主要介紹了js如何調(diào)用qq互聯(lián)api實(shí)現(xiàn)第三方登錄,需要的朋友可以參考下2014-03-03微信小程序授權(quán)登錄的最新實(shí)現(xiàn)方案詳解(2023年)
最近由于公司需要研究了一下微信小程序的開發(fā),特此記錄一下小程序登錄授權(quán)的流程,便于自己理解,也希望對(duì)他人有多幫助,下面這篇文章主要給大家介紹了關(guān)于微信小程序授權(quán)登錄的最新實(shí)現(xiàn)方案的相關(guān)資料,需要的朋友可以參考下2023-02-02js location.replace與location.reload的區(qū)別
js location.replace與location.reload的區(qū)別,經(jīng)常能用的到,需要的朋友可以可以下。2010-09-09