前言
在薄荷app的用戶信息頁(yè)看到在記錄身高時(shí)衔峰,利用左右滑動(dòng)刻度尺來(lái)取值即寡。原本以為是h5實(shí)現(xiàn)戈毒,但上網(wǎng)搜索后并沒(méi)有找到相關(guān)博客和文章,倒是有很多android的控件實(shí)現(xiàn)议经。所以就想自己實(shí)現(xiàn)一個(gè)看看斧账。
需求
因?yàn)橹皇亲鲆粋€(gè)demo,那就實(shí)現(xiàn)簡(jiǎn)單的效果就可以:
- 刻度區(qū)間[0煞肾,100]
- 有倒三角標(biāo)記咧织,指示當(dāng)前刻數(shù)
- 用戶左右滑動(dòng)刻度尺區(qū)域,能夠動(dòng)態(tài)獲取倒三角指示的刻數(shù)
效果圖
效果圖
實(shí)現(xiàn)過(guò)程
以下講述關(guān)鍵的實(shí)現(xiàn)步驟籍救,也可以直接下載文章最后的github源碼习绢。
頁(yè)面繪制
頁(yè)面其實(shí)很好繪制,一個(gè)刻度文本<span>節(jié)點(diǎn)和一個(gè)包裹刻度尺的<div>容器蝙昙。難點(diǎn)在于刻度尺的展示和倒三角的實(shí)現(xiàn)闪萄。
- 倒三角的實(shí)現(xiàn)
//html
<div id="triangle"></div>
//css樣式
#triangle {
width: 0;
height: 0;
margin: 0 auto;
z-index: 199;
border-top: 1rem solid rgb(190, 98, 75);
border-left: 1rem solid transparent;
border-right: 1rem solid transparent;
}
倒三角是一個(gè)沒(méi)有內(nèi)容的div,高度0奇颠,寬度0败去,為了讓其居中,設(shè)置marigin:0 auto烈拒。通過(guò)設(shè)置左右邊框透明为迈、上邊框1rem粗可以畫(huà)出倒三角的效果。
- 刻度尺實(shí)現(xiàn)
//html
<div id="ruler" data-offset="0">
<ul id="ruler-ul">
<li>
<span>10</span>
</li>
<li>
<span>20</span>
</li>
<li>
<span>30</span>
</li>
//更多的刻度
</ul>
</div>
//css樣式
#ruler-container {
position: relative;
overflow: hidden;
width: 20rem;
height: 5rem;
border: 1px solid rgb(147, 184, 47);
}
#ruler ul {
transform: translateX(10rem);
width: 100rem;
height: 4rem;
position: relative;
}
#ruler ul li{
width: 6.5rem;
height: 100%;
text-align: right;
background: url(./ruler.png) top left no-repeat;
background-size: 100px auto;
float: left;
list-style: none;
}
- 刻度尺其實(shí)是一個(gè)無(wú)序列表缺菌,每一個(gè)刻度都是其中一個(gè)列表項(xiàng)葫辐。
- ul元素的寬度盡量設(shè)置非常大,并將其父div的overflow屬性設(shè)置為hidden伴郁,保證列表項(xiàng)在一行上耿战。
- 刻度線使用一張背景圖片實(shí)現(xiàn),設(shè)置background-size和background屬性焊傅,可以讓其達(dá)到合適的排列效果剂陡。同時(shí)需要float:left消除空隙狈涮。list-style:none也是必須的,不然會(huì)有默認(rèn)的圓點(diǎn)鸭栖。
至此歌馍,頁(yè)面的布局算是完成了。
滑動(dòng)事件響應(yīng)
實(shí)現(xiàn)滑動(dòng)效果就是計(jì)算手指滑動(dòng)距離晕鹊,來(lái)設(shè)置#ruler的tansform:translateX(距離)樣式松却。
- 首先記錄手指觸碰到屏幕時(shí)的x坐標(biāo)
ruler.addEventListener('touchstart', function (event) {
//手指按下時(shí)的坐標(biāo)
offsetX = event.touches[0].clientX;
//初始化第一次滑動(dòng)的距離為0
moveBefore = 0;
});
- 當(dāng)手指在屏幕上滑動(dòng)時(shí)將其x坐標(biāo)記錄下來(lái),跟按下時(shí)的x坐標(biāo)相減計(jì)算出偏移量溅话,將該偏移量賦給#ruler的樣式晓锻,同時(shí)除以單位刻度的長(zhǎng)度unit獲取移動(dòng)的刻度數(shù),保留兩位小數(shù)顯示
rulerUl.addEventListener('touchmove', function (event) {
//獲取滑動(dòng)時(shí)手指的動(dòng)態(tài)坐標(biāo)
var move = event.touches[0].clientX;
//上一次計(jì)算出的刻度尺移動(dòng)距離
var offset = ruler.dataset.offset;
//原來(lái)是string飞几,轉(zhuǎn)換為float方便計(jì)算
offset = parseFloat(offset);
var tempMove = 0;
var len = 0;
//相對(duì)于手指按下時(shí)的距離砚哆,除以10是因?yàn)橐獙x轉(zhuǎn)換為rem單位
tempMove = move - offsetX;
tempMove /= 10;
//計(jì)算兩次滑動(dòng)間的距離
len = offset + (tempMove - moveBefore);
len = parseFloat(len);
//邊界判斷,最大偏移長(zhǎng)度65rem
if (len - 0.0 < 0 && len > -65) {
//將結(jié)果保存下來(lái)屑墨,下一次滑動(dòng)時(shí)取出參與計(jì)算
moveX = tempMove;
ruler.dataset.offset = len;
moveBefore = moveX;
//設(shè)置樣式
ruler.style = "transform: translateX(" + len + "rem)";
//顯示刻度躁锁,保留2位小數(shù)
num.innerText = -((len / unit).toFixed(2));
}
}, false);
源碼地址
總結(jié)
一時(shí)興起做了這個(gè)demo,簡(jiǎn)單的實(shí)現(xiàn)了刻度尺滑動(dòng)效果卵史。但是也有一些問(wèn)題:
- 因?yàn)楦↑c(diǎn)數(shù)精度問(wèn)題會(huì)出現(xiàn)無(wú)法滑動(dòng)到0或100的情況灿里,因?yàn)榇藭r(shí)已經(jīng)滿足滑動(dòng)事件中的if條件,后面的樣式修改等語(yǔ)句不會(huì)執(zhí)行程腹。
- 雖然使用了rem單位來(lái)處理不同設(shè)備匣吊,但是因?yàn)榭潭染€使用了背景圖片來(lái)實(shí)現(xiàn),不同的設(shè)備寬度下精度會(huì)受到影響寸潦。
- 我只是一個(gè)學(xué)了3個(gè)月前端的新人色鸳,代碼中肯定還有很多我不知道的不規(guī)范的地方,,希望能幫我指出见转。
如果能幫到你命雀,我將十分榮幸。