在项目中经常碰到详情效果有多个内容区块,需要根据快速导航做定位,如下记录实现的过程用作日后的参考。
实现分析:左侧作为可滚动区域class为side-nav-body
,右侧的快速定位区域class为side-nav-list
。其中side-nav-body
占据屏幕高度,并且多余内容内部可以滚动,而side-nav-list
需要常驻在顶部位置,所以在dom层级上两者应该是同一层位置,dom结构如下:
<div class="side-nav-body">
<div class="sect-overview"></div>
<div class="sect-basic"></div>
</div>
<ul class="side-nav-list">
<li>概览</li>
<li>基本信息</li>
</ul>
滚动:当点击li节点的时候需要触发div.side-nav-body
的滚动,触发之前我们需要计算滚动高度。这里需要使用到两个值,一个是offset
的值,一个是scollTop
的值,这里分别解释他们的具体含义。
offset()
的返回结果为dom结构距离浏览器的视口的顶部和最左边的距离,可以通过$('dom').offset()
得到形如 {top: 120, left: 580}
的结构。对于.side-nav-body
区域内没有padding
和滚动的情况,.side-nav-body
和.sect-overview offset()
的结果是一样的,对于.side-nav-body
内部有滚动的情况下,我们需要计算的就是这两个offset().top
的offset
。
scollTop()
的返回结果为内容区域的相对顶部滚动了多少,如果内容往上滚动了100px,那返回值就是100。
这里给出计算公式:
容器滚动高度 = 容器原滚动高度 + 需要偏移的高度 = 容器滚动高度 + 子容器距离视口顶部的距离-父容器距离视口顶部的距离
转化为示意表达式为:
let originScroll = container.scrollTop();
let offset = sect.offset().top - container.offset().top;
container.scrollTop(originScroll + offset)
在本例中为了增加动画效果,不直接使用scrollTop而是使用animate,最终的实现代码为:
function navTo(key) {
let container = $('.side-nav-body');
let sect = $(`.${key}`, container);
let offset = sect.offset().top - container.offset().top;
let originScroll = container.scrollTop();
body.animate({
scrollTop: originScroll + offset
}, 300)
}