拉勾网顶部轮播图的实现(二)

484 查看

Hi,大家好。上次拉勾网顶部导航完成了一部分,因为上下两个特效案例本身是没有多大联系的,并且原生JS的实现效果有一些小BUG需要完善,所以选择分开做,并且拖了好几天,真是抱歉。
好了现在来看代码吧。
首先是HTML代码部分:

    <div class="banner">
        <ul>
            <li class="box1"><img src="image/intro1.jpg" alt="">                
                <div class="box2">
                    <h2>婚礼纪</h2>
                    <em></em>
                    <p>一站式婚礼电商服务平台</p>
                </div>
            </li>
            <li class="box1"><img src="image/intro2.png" alt="">
                <div class="box2">
                    <h2>丽子美妆</h2>
                    <em></em>
                    <p>由麻省理工博士创办,专注于售卖化妆品一百年</p>
                </div>
            </li>
            <li class="box1"><img src="image/intro3.png" alt="">
                <div class="box2">
                    <h2>端点科技</h2>
                    <em></em>
                    <p>做最好的软件公司,盈利,高成长空间,专注技术</p>
                </div>
            </li>
            <li class="box1"><img src="image/intro4.png" alt="">
                <div class="box2">
                    <h2>来存吧</h2>
                    <em></em>
                    <p>专注银行票据理财</p>
                </div>
            </li>
            <li class="box1"><img src="image/intro5.jpg" alt="">
                <div class="box2">
                    <h2>任润科技</h2>
                    <em></em>
                    <p>高端互联网金融平台构架服务商</p>
                </div>
            </li>
            <li class="box1"><img src="image/intro6.jpg" alt="">
                <div class="box2">
                    <h2>淘维科技</h2>
                    <em></em>
                    <p>一款服务上万商户的产品</p>
                </div>
            </li>
        </ul>
    </div>

这个看起来应该比较简单,就是一个li块级元素包含着一个div元素遮罩层,我们的js和jquery代码都是让这个遮罩层的位置移动来完成整个效果,下面是css代码。

*{margin: 0;padding: 0;}
li {list-style: none;}
.box1{
    width:100px;
    height: 100px;
    overflow: hidden;
    position: relative;
    top: 200px;
    left: 300px;
    float: left;
    margin-right: 20px;
}
.box1 img {
    width: 100px;
    height: 100px
}
.box2{
    width: 100px;
    height: 100px;
    background-color: rgb(25,186,149);
    position: absolute;
    opacity: 0.7;
}
.box2 h2 {
    text-align: center;
}
.box2 p {
    text-align: center;
    font-size: 14px;
    margin-top: 10px;
}

大家如果要和上次的轮播图放一起的话,需要再把这部分的CSS样式再稍微修改一下,不过大致上是差不多的。
接下来是jquery代码,本来是想用原生JS来实现的,但是最后总是有一点小BUG解决不了,为了避免大家骂我坑爹,还是把JS代码放到最后,大家参考下就可以了。
jquery的代码经过我反复测试,应该是可以运行没有BUG的,代码如下:

$(function() {  
    $(".box1").bind("mouseenter mouseleave",function(e) {  
        var w = $(this).width();  
        var h = $(this).height();  
        var x=(e.pageX-this.offsetLeft-(w/2))*(w>h?(h/w):1);  
        var y=(e.pageY-this.offsetTop-(h/2))*(h>w?(w/h):1);  
        var direction=Math.round((((Math.atan2(y,x)*(180/Math.PI))+180)/90)+3)%4;  
        var eventType = e.type;  
        var position=[{left:0,top:-100},{left:100,top:0},{left:0,top:100},{left:-100,top:0}];  
        if(eventType== 'mouseenter'){  
            $(this).find(".box2").css(position[direction]).animate({left:0,top:0},400);  
            //这里要用this,如果用的是$(".box2")的话,会造成全部li都会在同时产生动画。
        }else{  
            $(this).find(".box2").animate(position[direction],400);  
        }  
    });  
}); 

现在给大家粗略的讲一下这个效果的实现过程,里面有的部分看的可能比较懵逼。
首先给class为box1的元素绑定一个鼠标移入移出产生相应效果的事件,并且传入相关参数。
之后是获取该元素的宽高设置成w和h,重点是后面三段代码。
这三段代码是用于获取鼠标是从元素的哪个方向进入的,以便于我们后面动画效果的实施。
因为这部分是从网上学的,所以还是把原文地址发上来,作者讲的很好,大家可以看一下:判断鼠标进入方向

获取到的direction是0,1,2,3中的一个数字,分别代表上下左右。
接下来做后续的效果,那我们的需求是要遮罩层box2从鼠标滑入的方向移动到box1上,例如从上方滑入的话,要求box2从位置{left:0px;top:100px}移动到{left:0px;top:0px},从其他方向进入的话也是一样,无非是初始位置改变,最终位置是不变的——即box1的位置。
现在我们来设置一个数组:

var position=[{left:0,top:-100},{left:100,top:0},{left:0,top:100},{left:-100,top:0}];  

从索引0,1,2,3分别代表着上下左右,之后我们再做一个判断:

if(eventType== 'mouseenter')

假如鼠标事件是鼠标滑入的,则执行以下代码:

$(this).find(".box2").css(position[direction]).animate({left:0,top:0},400);  

这里可能有的朋友要问了,$(this).find(".box2")这个部分不是多此一举了吗,直接调用$(".box2")不就可以了吗?
如果我们只是针对一张图片做这个动画效果的话,也就是说box1和box2都只有一个,那直接调用box2是没有问题的,但是如果有多个的话,最终的结果就是所有的box2元素同时产生动画效果。
为了针对一个单独的box1对象——即我们函数执行的当前对象,需要用到this。
最后一行代码则正好和上面是相反,box2从(0,0)的位置移动到鼠标滑出的位置,用animate方法来执行动画。
整个jquery代码大概就是这么个意思,应该还是不难理解的。
最后面我把JS实现的代码也放上来,原理是一样的,大致上的效果也可以实现,但是不知道为什么一直有BUG去不掉,大家参考下就行了,如果有什么解决方法可以提出来,因为本身我也是新人,很多东西都搞不懂,可以一起交流下。

<script>
window.onload=function(){
    var box1=document.getElementsByClassName('box1');
        // var box2=document.getElementById('box2');
        for(var i=0;i<box1.length;i++){
        box1[i].onmouseenter=function(e){
            var w=this.offsetWidth;
            var h=this.offsetHeight;
            var x=(e.pageX-this.offsetLeft-(w/2))*(w>h?(h/w):1);    
            var y=(e.pageY-this.offsetTop-(h/2))*(h>w?(w/h):1);   
            var direction=Math.round((((Math.atan2(y,x)*(180/Math.PI))+180)/90)+3)%4;
            var position=["left:0px;top:-100px","left:100px;top:0px","left:0px;top:100px","left:-100px;top:0px"]; 
            var ttt=this.getElementsByClassName('box2')[0];
            ttt.style.cssText=position[direction];
            setTimeout(function(){
                ttt.style.cssText="left:0px;top:0px;transition:all ease 0.4s";
            },1);
        }
        box1[i].onmouseleave=function(e){
            var w=this.offsetWidth;
            var h=this.offsetHeight;
            var x=(e.pageX-this.offsetLeft-(w/2))*(w>h?(h/w):1);    
            var y=(e.pageY-this.offsetTop-(h/2))*(h>w?(w/h):1);   
            var direction=Math.round((((Math.atan2(y,x)*(180/Math.PI))+180)/90)+3)%4;
            var position=["left:0px;top:-100px;transition:all ease 0.4s","left:100px;top:0px;transition:all ease 0.4s","left:0px;top:100px;transition:all ease 0.4s","left:-100px;top:0px;transition:all ease 0.4s"]; 
            var ttt=this.getElementsByClassName('box2')[0];
            ttt.style.cssText="left:0px;top:0px;";
            setTimeout(function(){
                ttt.style.cssText=position[direction];
            },1);
        }   
        }
}   
</script>