移動端滾動神器 better-scroll 系列篇四 原生js+BS 實現 城市列表,錨點定位

需求分析

在這裏插入圖片描述

思路分析

  1. 先做佈局
  2. 通過監聽右側導航的滑動或點擊,獲取當前Y軸位置,賦予列表相同的位置,實現列表的滾動
  3. 列表的滾動,獲取位置範圍,完成右側導航定位

一,頁面佈局

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width,user-scalable=no" />
<meta charset="UTF-8">
<title>城市列表</title>
<style type="text/css">
ul {
	margin: 0;
	padding: 0;
	list-style: none;
}
.list-wrapper{
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	overflow: hidden;
	background: #fff;
} 
.index-list-content{
	background: #fff;
	border-radius: 2px;
}

.index-list-title{
	padding: 14px 16px;
	font-size: 14px;
	line-height: 1.6;
	color: #333;	
}

.index-list-anchor{
	padding: 16px 16px 10px 16px;
	line-height: 1;
	font-size: 14px;
	color: #999;
	background: #f7f7f7;	
}

.index-list-item {
	position: relative;
	height: 50px;
	line-height: 50px;
	padding: 0 16px;
	font-size: 14px;
	color: #333;
}
.index-list-item:last-child{
	border: none;
}
.index-list-item_active{
	background: #ddd;	
}
.index-list-fixed{
	position: absolute;
	z-index: 1;
	top: 0;
	left: 0;
	width: 100%;
	padding: 16px 16px 10px 16px;
	box-sizing: border-box;
	font-size: 14px;
	line-height: 1;
	color: #999;
	background: #f7f7f7;	
}

.index-list-nav {
	position: absolute;
	z-index: 30;
	right: 0;
	top: 50%;
	transform: translateY(-50%);
	font-family: Helvetica;	
}
.index-list-nav ul {
	padding: 0;
	margin: 0;
}       
.index-list-nav li{
	padding: 6px 16px 0 16px;
	line-height: 1;
	text-align: center;
	box-sizing: border-box;
	font-size: 12px;
	color: gray;
}          
.index-list-nav .active {
	color: blue;
}
                
</style>
</head>
<body>
<div class="list-wrapper">
    <div class="scroll-content">
        <div class="index-list-content">
            <div class="index-list-title">
                定位城市: 
            </div>
            <ul>
                <li>
                    <h2 class="index-list-anchor">
                        ★熱門城市
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            北京市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            上海市
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        A
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            鞍山市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            安慶市
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        B
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
              
                            北京市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            巴音郭楞州
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            博爾塔拉州
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        C
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            成都市
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        E
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            鄂爾多斯市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            鄂州市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            恩施州
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        F
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            福州市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            佛山市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            防城港市
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        G
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            廣州市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            貴陽市
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        H
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            杭州市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            和田地區
                        </li>
                    </ul>
                </li>
                <li>
                    <h2 class="index-list-anchor">
                        Z
                    </h2>
                    <ul>
                        <li class="index-list-item border-bottom-1px">
                            鄭州市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            張家口市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            張家界市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            珠海市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            中山市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            自貢市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            資陽市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            棗莊市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            舟山
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            遵義市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            淄博市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            株洲市
                        </li>
                        <li class="index-list-item border-bottom-1px">
                            中衛市
                        </li>
                    </ul>
                </li>
            </ul>
        </div>
    </div>
</div>
<div class="index-list-nav">
    <ul>
        <li data-index="0" class="active"></li>
        <li data-index="1">
            A
        </li>
        <li data-index="2" class="">
            B
        </li>
        <li data-index="3" class="">
            C
        </li>
        <li data-index="4" class="">
            E
        </li>
        <li data-index="5" class="">
            F
        </li>
        <li data-index="6" class="">
            G
        </li>
        <li data-index="7" class="">
            H
        </li>
        <li data-index="8" class="">
            Z
        </li>
    </ul>
</div>
<div class="index-list-fixed" style="display: none;">
    A
</div>
<script type="text/javascript" src="./bscroll.js"></script>	
<script type="text/javascript" src="./city.js"></script>
</body>
</html>

由於js較大,分離開了

二,初始化(city.js)

  1. 封裝匿名自執行函數
  2. 獲取各個需要操作的元素
  3. 初始化
(function(){
    //獲取外框
    var list = document.querySelector(".list-wrapper");
    //獲取導航的ul
    var indexListNav = document.querySelector(".index-list-nav");
    //後面的步驟 setNav之後
    var indexListNavs = indexListNav.querySelectorAll("li");
    //獲取頂部索引
    var indexListFixed = document.querySelector(".index-list-fixed");
    //nav獲取之後操作 return index之後
    var indexListContent = document.querySelector(".index-list-content");
    //獲取ul下所有li
    var indexLists = indexListContent.children[1].children;
    //初始化
    var indexList = new BScroll(list,{
        //事件派發
        probeType:3
    })
})();

三,監聽右側列表的滑動或者點擊,獲取位置

爲了方便大家理解,我的調試步驟也在

	indexListNav.addEventListener("touchstart",(e)=>{
        //可以獲取到dom節點
        // console.log(e.target);
        //Y軸位置 座標
        // console.log(e.changedTouches[0].clientY);
        setIndex(e.changedTouches[0].clientY);

    })
    indexListNav.addEventListener("touchmove",(e)=>{
        // console.log(e.changedTouches[0].clientY);
        //可以獲取到dom節點
        setIndex(e.changedTouches[0].clientY);
    })
    //設置座標
    function setIndex(y){
        let index = getIndex(y);
        if(index < 0 || index >9){
            //沒有對應元素
            return;
        }
        //滾動到對應元素上去 li 過渡時間
        indexList.scrollToElement(indexLists[index],100);
    }
    //拿到座標
    function getIndex(y){
        //第二步 獲取它相對於可視區的距離
        var navTop = indexListNav.getBoundingClientRect().top;
        var h = 18; //nav li的高
        //計算一下 得到index
        // var index = y/18; 下方轉換

        // 轉換成相對於nav的距離
        var index = parseInt((y-navTop)/18); //0-8
        //打印出來看一下
        // console.log(index);
        return index;
    }

第一二步完美實現

第三步

定義一個設置右側導航active的方法

 //nav active 控制
    function setNav(index){
        //先獲取所有的a標籤
        indexListNavs.forEach((li)=>{
            li.classList.remove("active");
        })
        //效果演示
        indexListNavs[index].classList.add("active");
    }

監聽列表滾動事件,導航定位進行對應改變

    indexList.on("scroll",(e)=>{
 		//拿到y軸 做一個比較
        var y = -e.y; 
        //是個負值 爲了方便計算 轉一下 我們要獲取top值
        //排除定位城市:背景這一行 第0項  未超過第一項就不顯示頂部
        if(y < indexLists[0].offsetTop){
            setNav(0);
            //最後一步 第0項不需要顯示
            indexListFixed.style.display = "none";
            //演示 清掉所有的
            return;
        }
        //過了第[0]項 實際爲第一項 顯示它
        indexListFixed.style.display = "block";
        //到倒數第二項
        //循環indexLists 下面每個li 
        //最後一個單獨處理  因爲最後一項i+1這個表達式就不成立了
        for(var i = 0; i < indexLists.length - 1; i++){
            //滾動距離是否大於當前項,並且小於下一項,是的話,就說明還在當前項
            if(y >= indexLists[i].offsetTop && 
                y < indexLists[i+1].offsetTop){
                 setNav(i);  
                 //最後一步 給個值
                 indexListFixed.innerHTML  = indexLists[i].children[0].innerHTML;
                 return;
            }
        }
        setNav(indexLists.length - 1);
        //最後一項設置
        indexListFixed.innerHTML  = indexLists[indexLists.length - 1].children[0].innerHTML;
    })

大功告成,完結撒花

此篇博客爲本人原創
轉載請註明出處

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章