如何使悬停触发仅在带有jquery的半径边界的div中的圆形区域上触发动画

时间:2010-11-27 21:08:02

标签: jquery animation hover geometry

我不是程序员,我正在尽力解决这个问题,但经过几个小时的努力和头痛我放弃了,我正在寻求帮助。

我有一个圆形徽标(一个半径为px足以成为圆圈的div,其中包含一些文字),当我悬停在徽标后面时,我会有一个动画从徽标后面出来。

我注意到我的动画是在圆形徽标和带有徽标的div(它仍然是正方形)之间的“空白区域”上触发的。 目前我的脚本就是这样:

$("#logo").hover(function(event){     // Hovering
    myHover = "transition";
    $("#black").stop().animate({"top":"-200px"}, speed/2, function(){
        myHover = 1;
    });
},function(event){      // Finish hovering
    myHover = "transition";
    $("#black").stop().animate({"top":"0px"}, speed/2, function(){
        myHover = 0;
    });
});

我试着在网上和堆栈溢出上寻找能帮到我的东西,而我发现的最接近的是:

http://jsbin.com/oqewo - 来自另一个问题Accurately detect mouseover event for a div with rounded corners

我试图实现它,我确实提出了一些不够流畅的东西(我尝试调试试图在徽标上用鼠标前后移动以查看脚本的反应):< / p>

$(".myCircle").hover(
    // when the mouse enters the box do...
    function(){
        var $box = $(this),
        offset = $box.offset(),
        radius = $box.width() / 2,
        circle = new SimpleCircle(offset.left + radius, offset.top + radius, radius);

        $box.mousemove(function(e){
            if(circle.includesXY(e.pageX, e.pageY) && myHover != "transition"){
                $(this).css({"cursor":"pointer"});
                myHover = "transition";
                $("#black").stop().animate({"top":"-200px"}, speed/2, function(){
                    myHover = 1;
                });
            }else if(!circle.includesXY(e.pageX, e.pageY)){
                $(this).css({"cursor":"default"});
                myHover = "transition";
                $("#black").animate({"top":"0px"}, speed/2, function(){
                    myHover = 0;
                });
            }
       });

    },
    // when the mouse leaves the box do...
    function() {       
        //alert("in")
       //$(this).includesXY(e.pageX, e.pageY)
        myHover = "transition";
        $(this).css({"cursor":"default"});
        $("#black").stop().animate({"top":"0px"}, speed/2, function(){
            myHover = 0;
        });
    }
)

我插入了一个变量myHover = 0;在我的函数开始时因为我需要一个变量来让我知道动画何时完成,它隐藏在徽标后面或转换中。

我不知道WHEN和HOW如何使用.unbind属性所以我不会吸吮足够的cpu。 还有什么比mouseenter事件更好的吗?它会触发各种时间,只有当我在徽标上移动鼠标时才会触发,而不是在动画期间我将鼠标放在徽标上时。无论如何,任何关于解决这个问题的建议或修改都非常受欢迎:)

==========================

更新

我可能会找到一种方法,它似乎有用,但我不确定是否可以优化/清理它,或者如果我正确使用unbind,有人可以查看我的代码吗?

$(".myCircle").hover(
        // when the mouse enters the box do...
        function(){
            var $box = $(this),
            offset = $box.offset(),
            radius = $box.width() / 2,
            circle = new SimpleCircle(offset.left + radius, offset.top + radius, radius);

            $box.mousemove(function(e){
            if(circle.includesXY(e.pageX, e.pageY) && myHover != "transition1"){
                $(this).css({"cursor":"pointer"});
                myHover = "transition1";
                $("#black").stop().animate({"top":"-200px"}, speed/2, function(){
                    myHover = 1;
                });
            }

            else if(!circle.includesXY(e.pageX, e.pageY)){
                $(this).css({"cursor":"default"});
                if(myHover == 1 || myHover == "transition1"){
                    myHover = "transition0";
                    $("#black").stop().animate({"top":"0px"}, speed/2, function(){
                        myHover = 0;
                    });
                }
            }
       });

    },
    // when the mouse leaves the box do...
    function() {       
        if(myHover == 1 || myHover == "transition1"){
            myHover = "transition0";
            $(this).css({"cursor":"default"});
            $("#black").stop().animate({"top":"0px"}, speed/2, function(){
                myHover = 0;
            })
        };
        $("#container").unbind('mousemove');
    }
)

此代码中使用的SimpleCircle类,来自上面提到的演示,定义为:

function SimpleCircle(x, y, r) {
  this.centerX = x;
  this.centerY = y;
  this.radius = r;
}

SimpleCircle.prototype = {
  distanceTo: function(pageX, pageY) {
    return Math.sqrt(Math.pow(pageX - this.centerX, 2) + Math.pow(pageY - this.centerY, 2));
  },
  includesXY: function(x, y) {
    return this.distanceTo(x, y) <= this.radius;
  }
};

1 个答案:

答案 0 :(得分:1)

关于您的更新,一切看起来都不错。

通过颠倒两个if()参数的顺序,您可以获得轻微的性能升级,以便myHover != "transition1"成为第一个。 &&是短路的,因此如果myHover != "transition1"为false,则无需调用昂贵的圆圈包含检查。

同样在else if()上可能值得将一些变量设置为表示你已经设置了光标以停止连续调用。

查看SimpleCircle类,它所做的唯一昂贵的操作是两个电源调用和一个平方根(Math.pow() x 2 + Math.sqrt())。是否值得尝试更快地得到它是有争议的,只有优化我能想到的是检查坐标是否在圆圈内的方形内,这是四个快速比较,这覆盖了50%的内部点,但显然减缓了其他50%的积分。要查看它是否有所改进,您必须对其进行测试。

Square inside a circle inside a square