移动端滚动神器 better-scroll 系列篇四 原生js+BS 实现 城市列表,锚点定位

简介: 笔记

需求分析



4.png


思路分析



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

大功告成,完结撒花


目录
相关文章
|
2天前
|
前端开发 JavaScript
前端 js 经典:Object 常用原生方法
前端 js 经典:Object 常用原生方法
10 2
|
2天前
|
前端开发 JavaScript
前端 js 经典:array 原生方法
前端 js 经典:array 原生方法
7 1
|
2天前
|
JavaScript 索引
jQuery 实现 图片框切换【与原生 JS 对比】
jQuery 实现 图片框切换【与原生 JS 对比】
|
3天前
|
监控 JavaScript 前端开发
超越原生:探索Node.js中最佳文件系统三方库
超越原生:探索Node.js中最佳文件系统三方库
|
3天前
countup.js包实现数字滚动-大屏项目
countup.js包实现数字滚动-大屏项目
6 1
|
3天前
|
存储 JavaScript 前端开发
Angular.js 如何绘制列表
Angular.js 如何绘制列表
11 2
|
3天前
|
JavaScript 前端开发 索引
JavaScript array 原生 reduce 方法的模拟实现
JavaScript array 原生 reduce 方法的模拟实现
8 2
|
4天前
|
JavaScript 定位技术 API
[JS]百度地图设置城市
[JS]百度地图设置城市
14 1
|
4天前
|
JavaScript 计算机视觉
原生js通过年龄判断是否可以抽奖
原生js通过年龄判断是否可以抽奖
11 0
|
4天前
|
存储 JavaScript 前端开发
原生JS如何实现验证码
原生JS如何实现验证码
14 0