用于'鼠标方向'悬停的jQuery动画

时间:2010-09-02 12:25:31

标签: jquery jquery-animate

我正在尝试模拟悬停在图像上的效果,覆盖的半透明图像将从鼠标来自的方向淡入。当鼠标离开图像时(淡出+移开)

,反之亦然

我为此准备了test page。继续检查,它将阐明所期望的效果。

我为此定义了一个HTML结构:

    <div class="overlayLink">
        <img src="assets/work/thumbnails/kreatude.jpg" alt="Kreatude" />
        <div class="overlayLink_overlay_bg">&nbsp;</div>
        <div class="overlayLink_overlay_fg">
            <span class="overlayLink_overlay_link"><a href="#">View Case Study</a></span>
            <div class="top">&nbsp;</div>
            <div class="left">&nbsp;</div>
            <div class="right">&nbsp;</div>
            <div class="bottom">&nbsp;</div>
        </div>
     </div>

以及以下JS(我正在使用jQuery):

jQuery(document).ready(function () {
    ourWork();
});

function ourWork(){
    var inHandler = function(){
        var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
        var divClass = inClass;

        blue_bg.stop(true,true).fadeIn();
        var ml,mt;
        if(divClass == 'left'){
            ml = -260;
            mt = 0;
        }
        else if(divClass == 'right'){
            ml = 260;
            mt = 0;
        }
        else if(divClass == 'top'){
            ml = 0;
            mt = -140;
        }
        else if(divClass == 'bottom'){
            ml = 0;
            mt = 140;
        }       

        //positioning
        jQuery(this).find('a').css({
            'marginLeft': ml + 'px',
            'marginTop' : mt + 'px'
        });


        //animation
        jQuery(this).find('a').stop(true,true).animate({
            "marginLeft": "0px",
            "marginTop": "0px"
        }, "slow");
    }
    var outHandler = function(){
        var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
        var divClass = outClass;

        blue_bg.stop(true,true).fadeOut();
        var ml,mt;
        if(divClass == 'left'){
            ml = -260;
            mt = 0;
        }
        else if(divClass == 'right'){
            ml = 260;
            mt = 0;
        }
        else if(divClass == 'top'){
            ml = 0;
            mt = -140;
        }
        else if(divClass == 'bottom'){
            ml = 0;
            mt = 140;
        }        

        //animation
        jQuery(this).find('a').stop(true,true).animate({
            "marginLeft": ml + "px",
            "marginTop": mt + "px"
        }, "slow");

    }

    var inClass, outClass;
    jQuery('.overlayLink_overlay_fg div').hover(function(){        
        inClass = jQuery(this).attr('class');
    },function(){       
        outClass = jQuery(this).attr('class');
    });

    jQuery('.overlayLink').mouseenter(inHandler).mouseleave(outHandler);
}

解释

基本上我在图像顶部有四个绝对定位的div,当我将鼠标悬停在其中一个div(.overlayLink_overlay_fg div)上时,我知道方向(左,上,下,右)我把悬停的类名称变量中的div(var inClass和var outclass)

一旦我将鼠标悬停在覆盖图像区域的div上(.overlayLink),我从inClass或outClass变量请求方向并执行动画(inHandler,outHandler)

然而这一切似乎都有效,当你快速移动鼠标时会有点小问题,现在我问问题是什么(导致故障)以及如何修复用我现在的代码。

提前致谢

7 个答案:

答案 0 :(得分:44)

也许你应该考虑不要将div用作“热点”,而是使用一些Math和Javascript来找到鼠标进入并离开div的点。这避免了重叠/间隙问题。 basicaly下面的代码将4个三角区域中的div分开。当鼠标移过它时,每个区域都会返回一个数字。代码需要一些微调,你必须自己决定绑定和取消绑定事件的位置。但我认为这会消除大部分闪烁问题。

$(".overlayLink").bind("mouseenter mouseleave",function(e){

/** the width and height of the current div **/
var w = $(this).width();
var h = $(this).height();

/** calculate the x and y to get an angle to the center of the div from that x and y. **/
/** gets the x value relative to the center of the DIV and "normalize" it **/
var x = (e.pageX - this.offset().left - (w/2)) * ( w > h ? (h/w) : 1 );
var y = (e.pageY - this.offset().top  - (h/2)) * ( h > w ? (w/h) : 1 );

/** the angle and the direction from where the mouse came in/went out clockwise (TRBL=0123);**/
/** first calculate the angle of the point, 
 add 180 deg to get rid of the negative values
 divide by 90 to get the quadrant
 add 3 and do a modulo by 4  to shift the quadrants to a proper clockwise TRBL (top/right/bottom/left) **/
var direction = Math.round((((Math.atan2(y, x) * (180 / Math.PI)) + 180 ) / 90 ) + 3 )  % 4;


/** do your animations here **/ 
switch(direction) {
 case 0:
  /** animations from the TOP **/
 break;
 case 1:
  /** animations from the RIGHT **/
 break;
 case 2:
  /** animations from the BOTTOM **/
 break;
 case 3:
  /** animations from the LEFT **/
 break;
}});
当然,获得方向的简短符号应该是:

var direction =  Math.round( Math.atan2(y, x) / 1.57079633 + 5 ) % 4

其中1.57 ...是Math.PI / 2这对我来说更难以解释,因为它会跳过度转换。

答案 1 :(得分:1)

从根本上说,鼠标移动事件发生的是一系列点而不是曲线,因为我们感知到屏幕上的移动。移动鼠标的速度越快,点之间的间距越大,鼠标可以移动的对象越大而不接触。因此,理想情况下,您需要知道在着陆到对象之前最后一个鼠标位置的方向,并从中计算出它接近的方向。即你需要不断跟踪整个页面上的鼠标位置,以确保每次都能正常工作。

答案 2 :(得分:0)

您可以尝试使用图像映射,将处理程序附加到定义的区域,而不是使用绝对定位的div来围绕图像。只需将边界区域定义得足够厚,即使它移动得相当快,也可以检测到鼠标移动。

答案 3 :(得分:0)

如果您从左向右快速滑动鼠标以使其穿过3个矩形

     [ 1 ] [ 2 ] [ 3 ] 

鼠标通过右边框div退出矩形#2后,立即通过左边框div输入矩形#3。但是,当矩形#3通过其左边界div输入时,赋值inClass =“left”outClass =“left”发生在矩形#2的outHandler被触发之前。

答案 4 :(得分:0)

如果我要实现此功能,请按照以下方式进行操作:

  1. 创建定义图像顶部,底部,左侧和右侧边框的图像映射区域。
  2. 对于你想要这种情报的每张图片(即它输入的是哪一面,它离开了哪一面): a)跟踪 sideEntered - 此值仅分配一次;每当进入图像 - 地图边界区域时,其鼠标悬停处理程序将参考sideEntered并仅在尚未分配时分配; b)跟踪 lastSideTouched - 每当输入图像映射区域时,mouseoverhandler重新分配此变量 c)当鼠标离开矩形时,离开处理程序查询 lastSideTouched 并将 sideEntered 重置为null
  3. 每个矩形都应该有自己的处理程序,因此两个重要的值 sideEntered lastSideTouched 在其处理程序的范围内被封装

答案 5 :(得分:0)

  • 问题是什么(导致故障)

此代码(以及inClass&amp; outClass的使用)存在问题。您正在更改事件处理程序中使用的全局变量的状态。

var inClass, outClass; 
jQuery('.overlayLink_overlay_fg div').hover(function(){         
    inClass = jQuery(this).attr('class'); 
},function(){        
    outClass = jQuery(this).attr('class'); 
}); 

此代码假定outClass是由“local”div设置的,但coulsd是由邻近的顶级div设置的

    var outHandler = function(){        
    var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');        
    var divClass = outClass;   
  • 如何使用我当前的代码修复它?

不要将此作为单个全局变量进行管理,尝试使用Isolated mannor进行管理。

这是一个评论: 我还没有测试过这段代码

    jQuery('.overlayLink_overlay_fg div').hover(function() {
        jQuery(this).parents('.overlayLink').attr('mouseEnterClass', jQuery(this).attr('class'));
    }, function() {
        jQuery(this).parents('.overlayLink').attr('mouseLeaveClass', jQuery(this).attr('class'));
    });

在您的处理程序中,请参考这些新数据。

    var outHandler = function() {
        var blue_bg = jQuery(this).find('.overlayLink_overlay_bg');
        var divClass = jQuery(this).attr('mouseLeaveClass');
        ....
      }

这个woulod解决了全局变量问题。我不确定如果'hover'事件在动画完成之前发生会发生什么。

编辑: 修复了代码问题。

答案 6 :(得分:0)

这是一个简单的解决方案,但是在mouseenter事件中边缘需要改进。

在鼠标进入事件中,我给了它5%(0%&0%)(100%&100%)的差异,只是为了快速移动光标来捕获光标,这是需要修复的错误。

enter image description here

const div = document.querySelector('div');

const mouseLeave = (e) => {
    e.preventDefault();
    e = e || window.event;

    // get box properties
    let a = e.target.getBoundingClientRect();
    let w = a.width;
    let h = a.height;

    // get x,y
    const x = e.pageX - a.left;
    const y = e.pageY - a.top;

    //* detect mouse out
    if (x >= w) console.log('out-right');
    if (x <= 0) console.log('out-left');
    if (y >= h) console.log('out-bottom');
    if (y <= 0) console.log('out-top');
}

const mouseEnter = (e) => {
    e.preventDefault();
    e = e || window.event;

    // get box properties
    let a = e.target.getBoundingClientRect();
    let w = a.width;
    let h = a.height;

    // get x,y
    const x = e.pageX - a.left;
    const y = e.pageY - a.top;

    // get positions by percentage
    const X = (x / w) * 100;
    const Y = (y / h) * 100;

    //* detect mouse in
    if ((X >= 0 && X <= 100) && (Y >= 0 && Y <= 5)) console.log('in-top');
    if ((X >= 0 && X <= 100) && (Y >= 95 && Y <= 100)) console.log('in-bottom');
    if ((Y >= 0 && Y <= 100) && (X >= 95 && X <= 100)) console.log('in-right');
    if ((Y >= 0 && Y <= 100) && (X >= 0 && X <= 5)) console.log('in-left');
}

div.addEventListener('mouseleave', mouseLeave, true);
div.addEventListener('mouseenter', mouseEnter, true);
div {
    width: 300px;
    height: 300px;
    outline: 1px solid blue;
    margin: 50px auto;
}
<div></div>