zoukankan      html  css  js  c++  java
  • jQuery实现拉勾穿墙效果

    A 预备知识

    A1 思路

    HTML结构是每一个展示框都附带了一个随着鼠标滑过的遮罩层(mask)。每当鼠标在展示框上移入移出的时候,判断鼠标的方向,让遮罩层来跟随鼠标的移动。
    由于遮罩层只有一个,每次鼠标移入时,让遮罩层瞬间定位,然后沿着鼠标的方向进入,最终的目标就是和展示框的位置完全重合。
    离开时正好相反,起点是和展示框完全重合的位置,终点就是遮罩层刚刚离开展示框。
    行为如下图所示:

    穿墙演示.png

    A2 知识储备

    • 一丢丢平面几何的知识
    • js中盒子模型属性
    • jQuery的animate动画
    • 事件源的属性

    B 代码堆积

    B1 HTML结构

    <ul id="list">
    	<li>
    		![](images/aiqiyi.jpg)
    		<div class="mask">爱奇艺</div>
    	</li>
            ...
    </ul>
    

    img是要穿过的图片
    mask是遮罩层
    li相对定位,mask绝对定位

    B2 绑定事件

    var $li = $('#list').children('li');
    $li.each(function () {
    	fn($(this));
    });
    

    遍历所有的li,在函数fn里为其绑定移入和移出事件

    function fn($box) {
        var nWidth = $box.outerWidth();
        var nHeight = $box.outerHeight();
        var $mask = $box.children('.mask');
    }
    

    获得每个li的宽高,这个宽高也是遮罩层运动的距离。
    获得遮罩层。

    //在fn里,为每个li绑定移入事件
    $box.mouseenter(function (e) {
        var x = e.clientX - $(this).offset().left - this.offsetWidth / 2;
        var y = $(this).offset().top + this.offsetHeight / 2 - e.clientY;
    };
    

    此入的x和y,是相对于各自的li的中心。

    获得鼠标坐标值.png

    鼠标的实时位置,相对于li的中心点的坐标,可以根据上图这样来算出

    y = li高度/2 - (鼠标实时距页面边距b - li相对页面的偏移a);
    x = 鼠标实时距页面边距d -  li相对页面的偏移c - li宽度/2;
    

    备注:li距页面的边距不一定就是通过ele.offset.top来获得,如果中间嵌套了其他定位元素,可以由其他盒子模型属性来获得。

    因为要根据这个xy值来判断,是哪个方向,而且离开的时候还是要根据这个来判断,所以将判断方法封装成一个方法,返回值有四种情况,来代码是从哪个方向进入和移出。

    function getDirction(x, y) {
        //获得方向的弧度制
        var rad = Math.atan2(y, x);
        //获得方向的角度制,具体角度分布见下图
        var angle = 180 * rad / Math.PI;
        //将角度经过一系列运算,最终得到四个方向四个值,返回出去
        return Math.round((angle + 180) / 90) % 4;
    }
    

    得到方向.png

    由于得到的5个值,左边进入有两值,再进行%4操作,就可以精简为四个值,分别0代表从左侧进入,1借债有从下侧进入,2代码从右侧进入,3代表从上侧进入。

    在鼠标移入事件中得到方向,来控制mask的进入初始位置。

    $box.mouseenter(function (e) {
        var x = e.clientX - $(this).offset().left - this.offsetWidth / 2;
        var y = $(this).offset().top + this.offsetHeight / 2 - e.clientY;
        var val = getDirction(x, y);
        switch (val) {
            case 0:
                $mask.css({'left': -nWidth, 'top': 0});
                break;
            case 1:
                $mask.css({'top': nHeight, 'left': 0});
                break;
            case 2:
                $mask.css({'top': 0, 'left': nWidth});
                break;
            case 3:
                $mask.css({'top': -nHeight, 'left': 0});
        }
        //无论从哪个方向进入,最终的目标点都是一样的,即和li完全重合,就是起始的位置不同
        $mask.stop().animate({'left': 0, 'top': 0});
    });
    

    同样由此可以得出,移出事件

    $box.mouseleave(function (e) {
        var x = e.clientX - $(this).offset().left - this.offsetWidth / 2;
        var y = $(this).offset().top + this.offsetHeight / 2 - e.clientY;
        var val = getDirction(x, y);
        var target;
        switch (val) {
            case 0:
                target = {'left': -nWidth, 'top': 0};
    	        break;
            case 1:
    	        target = {'top': nHeight, 'left': 0};
    	        break;
    	    case 2:
    	        target = {'top': 0, 'left': nWidth};
    	        break;
    	  case 3:
    	        target = {'top': -nHeight, 'left': 0};
        }
        $mask.stop().animate(target);
    });
    

    移出事件正好和移入相反,移出的时候起始点是一样的,而离开的时候需要判断是从哪个方向出去。

    C 在线预览

    在线预览

  • 相关阅读:
    合并代码与前后端联调分别什么意思?
    自动化执行禅道 自动化写用例
    01- 计算机网络体系结构
    12- 输出重定向
    11- 文件权限管理命令
    10- sudo,exit命令
    09- Linux下压缩和解压命令
    021- Java语言基础-基本数据类型的一些问题和总结
    根据上传的MultipartFile通过springboot转化为File类型并调用通过File文件流的方法上传特定服务器
    文件上传报错java.io.FileNotFoundException拒绝访问
  • 原文地址:https://www.cnblogs.com/changzhenan/p/7071619.html
Copyright © 2011-2022 走看看