需求分析
思路分析
- 先做布局
- 通过监听右侧导航的滑动或点击,获取当前Y轴位置,赋予列表相同的位置,实现列表的滚动
- 列表的滚动,获取位置范围,完成右侧导航定位
一,页面布局
<!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)
- 封装匿名自执行函数
- 获取各个需要操作的元素
- 初始化
(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;
})
大功告成,完结撒花
此篇博客为本人原创
转载请注明出处