先上效果图:划过之后粘在页面之上,之后又取下来的感觉
核心思路:
- 1.你看到的粘在上面的nav的确是本体,不过已经被position:fixed,所以才有这种固定的效果;
- 2.当本体fixed之后,因为脱离文档流,下面的元素势必会上来,这里会事先clone一个nav,insertBefore到本体的位置,然后让他opacity:0,再hide;
- 3.当滑动到某个nav的位置的时候,本体display:fixed,clone体show()出来,撑住场面,不让页面散掉,当滑动小于某个距离的时候,clone体继续hide(),本地不再fixed,就是这么一个思路;
下面看看具体代码的实现过程吧:场景设定是 nav 来Stick up
Step0:我用的这个结构
<div id="content">
<div id="content-1" class="content-item">
<div class="nav">nav1</div>
<div class="aside">aside1</div>
<div class="main">main1</div>
</div>
<div id="content-2" class="content-item">
<div class="nav">nav2</div>
<div class="aside">aside2</div>
<div class="main">main2</div>
</div>
<div id="content-3" class="content-item">
<div class="nav">nav3</div>
<div class="aside">aside3</div>
<div class="main">main3</div>
</div>
</div>
Step1:一些后面需要用到的变量
var $nav = $('.nav'),
navH = $nav.height(),
navW = $nav.width(),
offsetLeft = $nav.offset().left,
offsetTop = $nav.offset().top;
var $cloneNav = $nav.clone().css('opacity',0).insertBefore($nav).hide();
//这里的 $cloneNav 是这样一路下来的
Step2:如何判断是否该元素是否到了该position:fixed?
$(window).on('scroll',function(){
var scrollTop = $(this).scrollTop();
if(scrollTop>= offsetTop){
if(!isFixed()){
setFixed();
}
}else{
if(isFixed()){
unsetFixed();
}
}
});
这里先把思路理出来,当页面滚动的时候,“页面滚动的距离”是否大于“自己在页面的偏移的距离”,
大于就证明到了,就开始判断是否已经fixed,没有就setFixed,假如小于这个距离,就判断是否fixed,如果fixed就解除fixed;注意这里并没有把浏览器高度拉进来,是因为我是让他固定在浏览器上方;这一点和以后要说的懒加载又有点不一样,先挖个坑在这里;
Step3:如何setFixed呢?又是如何unsetFixed呢?
function setFixed(){
$nav.attr('position-fixed',true)
.css({
position:'fixed',
top:0,
left:offsetLeft,
'z-index':7,
width:navW,
height:navH,
margin:0
});
$cloneNav.show();
}
function unsetFixed(){
$nav.removeAttr('position-fixed').removeAttr('style');
$cloneNav.hide();
}
用到了jQuery的attr(),设置一个自定义标签,让经过set之后的元素有一个标记,然后用.css()来操纵本体,最后让clone体show出来,撑住场面,让页面不至于散架;
后面的解除fixed,就是把自己的自定义标签去除掉,并且把style(这里通过js操纵的样式都加在行内去了,所以用style来干涉),最后让clone体功成身退的hide掉
Step4:那么最终的问题,工具全部齐活了,最后的判断条件怎么写呢?
function isFixed(){
return !!$nav.attr('position-fixed');
}
这里用的就是我设置的自定义标签,省去了一些功夫,直接判断是否存在这个标签,用了!!两次转换,因为已经fixed的话,返回的就是true,但是假如根本没有fixed,这个自定义标签就不会存在,就会使undifined,所以两次转换之后变成false,达到效果;
具体细节和可以上github查看