手记

拉勾网顶部轮播图的实现(一)以及简单闭包的应用

一直觉得拉勾网的顶部导航轮播特别有意思,静态页面图如下:

滑动右侧的三张缩略图,可以看到左侧大图部分会上下滑动。另外鼠标移到下方的6张图上时,会有半透明的遮罩层出现,并且出现的方式会跟随鼠标移入方向的不同而随之改变,具体的动态效果可以到网站上查看。
那么我们这次先实现上面部分导航的效果,遮罩层的实现放到之后我们再进行分解(涉及到的代码比较繁杂,有兴趣的朋友可以自己搜索一下源代码)。
先把HTML和CSS部分的代码放上来吧。
HTML的代码显示有问题,这边我把截图放上来吧,大家看一下就可以了,非常简单。


CSS代码部分如下:
<style>

    .clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; } 
    .clearfix { *zoom:1; } 
    *{
        margin: 0;
        padding: 0;
    }
    ul {
        list-style-type: none;
    }
    a {
        text-decoration: none;
    }
    .container {
        width: 750px;
        margin: 100px auto; 
        overflow: hidden;
        height: 160px;
    }
    .content{
        float: left;

    }
    .content li+li {
        margin-top: -3px;
    }
    .control {
        float: right;
        width: 121px;
        height: 160px;
        position: relative;
        right: 0;
        top: 0;
    }
    .control li {
        width: 113px;
        height: 42px;
        border: 4px solid #ccc;
        position: relative;
    }
    .control li+li {
        margin-top: 5px;
    }
    .control span {
        background: url(image/control_current.png) no-repeat;
        width:137px;
        height: 50px;
        position: absolute;
        z-index: 1;
        left: -6px;
    }
    #bg-1 {
        transition:all 0.2s;
    }
    #content {
        transition:all 0.2s;
    }
    .banner {
        width: 750px;
        top: 275px;
        left: 50%;
        margin-left: -375px;
        position: absolute;
        height: 113px;
        overflow: hidden;
    }
    .banner li{
        float: left;
        border: 1px solid #e8e8e8;
    }
    .banner li+li {
        margin-left: 12px;
    }
    .hot-info {
        width: 113px;
        height: 113px;
        color: #fff;
        background-color: rgb(25,186,149);
        opacity: 0.8;
        transition: all 0.3s;
    }
    .hot-info h2{
        padding-top: 10px;
        text-align: center;
    }
    .hot-info em {
        display: block;
        width: 99px;
        height: 5px;
        background-color: rgb(94,207,181);
        margin:4px 7px 10px;
    }
    .hot-info p{
        line-height: 18px;
        font-size: 12px;
        margin: 6px 8px;
    } 
    .banner ul li:hover .hot-info {
        margin-top:-116px;
    }

</style>

接下来就是JS的实现:

window.onload=function(){
    function $(id){return typeof id==='string'?document.getElementById(id):id;}
    var control=$('control');
    var lis=control.getElementsByTagName('li');
    var span=$('bg-1');
    var content=$('content');
    var banner=$('banner');
    var imgs=banner.getElementsByTagName('img');
    var info=document.getElementsByClassName('hot-info');
    for (var i=0;i<lis.length;i++){
        lis[i].onmouseover=function(i){
        return function(){
            span.style.marginTop=i*55+"px";
            content.style.marginTop=-i*160+"px";
        }
    }(i);
}
}

可能大家看到这里就觉得这个东西也太简单了,不就是获取一下元素,然后再做一下for循环,添加一个onmouseover事件控制相关元素的css属性就完事了吗?
还有你这个for循环里面为什么还要套一个function?,不是应该这样子就可以了吗?

    for (var i=0;i<lis.length;i++){
        lis[i].onmouseover=function(){
            span.style.marginTop=i*55+"px";
            content.style.marginTop=-i*160+"px";
            }
        };

但是实际上,测试的时候你就会发现根本没有任何效果,可以输入一个console.log(i)在网页上打开控制台看下输出i的值到底是多少。
按理来说的话,输出的值应该是这样子的:

但是实际上你会发现,显示的是这样的:

就是这个原因导致我们的动态效果没有办法实现。
所以这个时候我们就发现上面正确代码里面添加的匿名函数的作用了,但是具体是怎么实现的呢?
首先要了解这个匿名函数是一个立即执行的函数,我们把 i 作为一个参数传给立即执行函数,这个函数执行后,i 转变成一个内部变量,外部函数无法获取到,这样局部变量i和全局变量i就可以很容易的区分开来,并且这个局部 i 就被保存下来并且被内部函数调用。
这个其实就是闭包的作用体现,这样可以做到正确的获取 i 的值(0,1,2),而不是获取到最终循环的值(2)。
到这里,大家应该都可以明白这个轮播图例子的实现原理了。
接下来,可以在CSS相关元素的样式中设置:
transition:all 1s;
就可以实现两侧图片的顺畅动画,至此我们的顶部轮播图片的制作也完成了,当然也可以不设置CSS的transition,用原生JS settimeout来控制图片在一定时间内的移动来完成动画,不过这个就确实比较麻烦。
那先到这里,后面会继续完成底部鼠标移入显示遮罩层的实现。

*PS 幸好有朋友提醒我,原来我把自动播放的代码忘掉了,我把原来的函数重新封装整理了一下,全部JS代码如下:

window.onload=function(){
    function $(id){return typeof id==='string'?document.getElementById(id):id;} 
    var control=$('control');
    var lis=control.getElementsByTagName('li');
    var span=$('bg-1');
    var content=$('content');
    var banner=$('banner');
    var imgs=banner.getElementsByTagName('img');
    var info=document.getElementsByClassName('hot-info');
    var timer=null;
    var index=0;
    // 自定义一个定时器timer
    // 自定义一个标签index用于控制自动播放:
    timer=setInterval(autoPlay,5000);
    // 初始化定时器timer
        content.onmouseover= control.onmouseover=function(){
            clearInterval(timer);
            change();
        }
        control.onmouseout=function(){
            timer=setInterval(autoPlay,5000);
        }
    function autoPlay(){
        index++;
        if(index>=lis.length){
            index=0;
        }
        span.style.marginTop=index*55+'px';
        content.style.marginTop=-index*160+'px';
    }
    function change(){
        for (var i=0;i<lis.length;i++){
            lis[i].onmouseover=function(i){
            return function(){
                span.style.marginTop=i*55+"px";
                content.style.marginTop=-i*160+"px";
                index=i;
//这个index=i是非常重要的一步,change()函数调用的参数是i,而autoPlay()的参数是index,为了让光标移开头部区域后能继续执行autoPlay,并且按照 change()函数给定的那个页签向下播放,所以需要把参数i赋值给index;
                }
            }(i);
        }
    }
}

函数部分就不再做过多的解释了,只是简单的定义了一个index,然后每隔5秒做一次递加,两边图片的位置也随之改变。再定义鼠标移入清除定时器,移出开启定时器就可以了,并且把原来的函数定义成一个change()函数方便调用。

83人推荐
随时随地看视频
慕课网APP

热门评论

能否认真一点儿, 整个全一点儿的

var banner=$('banner'); 

var imgs=banner.getElementsByTagName('img');

 var info=document.getElementsByClassName('hot-info')
没有这个id啊为什么要获取呢????不明白啊

老师,啥时候更新第二部分,自己做了下,有些地方做不出来,期待ing...

查看全部评论