移动端滚动神器 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;
    })

大功告成,完结撒花

此篇博客为本人原创
转载请注明出处

猜你喜欢

转载自blog.csdn.net/qq_35942348/article/details/103085750