如何使用jquery使悬停仅在具有半径边框的div中的圆形区域上触发动画
我不是程序员,我正在尽力解决问题,但经过几个小时和头痛后,我放弃了,并寻求帮助。
我有一个圆形徽标(一个具有足够半径 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 - 来自另一个问题准确检测圆角div的鼠标悬停事件
我尝试实现它,但确实得到了一些作为动画不够平滑的东西(我尝试调试尝试用鼠标在徽标上前后移动以查看脚本的反应):
$(".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;在我的函数开始时,因为我需要一个变量来让我知道动画何时完成、它隐藏在徽标后面或在转换中。
而且我不知道何时以及如何使用 .unbind 属性,所以我不会占用足够的CPU。 还有什么比 mouseenter 事件更好的吗?它会触发各种时间,并且仅当我将鼠标移动到徽标上时才会触发,而当我在动画期间将鼠标放在徽标上时则不会触发。不管怎样,任何关于解决这个问题的建议或修改都是非常受欢迎的:)
============================
更新< /strong>
我可能会找到一种方法,它似乎有效,但我不确定是否可以优化/清理它,或者如果我正确使用取消绑定,有人可以检查我的代码吗?
$(".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;
}
};
I am not a programmer, and I am trying my best to solve the situation but after several hours and headache I give up and I am asking for help.
I have a circular logo (a div with enough radius px to become a circle and some text in it), and I have an animation that come out from behind the logo when I hover on it.
I noticed that my animation it triggers on the "empty area" between the circular logo and the div that hold the logo (that it is still a square).
At the moment my script it is this:
$("#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;
});
});
I tried looking on the web and on stack overflow to find something that will help me, and the nearest thing that I found it is this:
http://jsbin.com/oqewo - from this other question Accurately detect mouseover event for a div with rounded corners
I tried to implement it and I did come out with something that it is not smooth enough as animation (I tried to debug trying to move back and forward with the mouse on the logo to see the reaction of the script):
$(".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;
});
}
)
I inserted a variable myHover = 0; at the start of my functions because I needed a variable that would let me know when the animation is completed, it is hidden behind the logo, or in transition.
And I don't know WHEN and HOW to use the .unbind property so I will not suck enough cpu.
Is there anything better than mouseenter event? It triggers various time, and only when I move the mouse on the logo, and not when I have the mouse on the logo during the animation. Anyway any suggestion or revision of any kind on approach this problem it is more than welcome :)
==========================
UPDATE
I might find a way, it seems to work, but I am not sure if it is possible to optimise/clean it, or if I am using unbind properly, someone can check my code?
$(".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');
}
)
The SimpleCircle
class used within this code, from the demo mentioned above, is defined as:
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;
}
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
关于您的更新,一切看起来都很好。
通过颠倒两个
if()
参数的顺序,使myHover != "transition1"
位于第一个,您可能会获得轻微的性能提升。&&
是短路的,因此如果myHover != "transition1"
为 false,则不需要调用昂贵的圆包含检查。另外,在 else if() 上,可能值得将一些变量设置为表示您已经设置光标以停止连续调用的值。
看一下
SimpleCircle
类,它执行的唯一昂贵的操作是两次幂调用和一个平方根 (Math.pow() x 2 + Math.sqrt()
)。是否值得尝试获得更快的速度是有争议的,我能想到的唯一优化是检查坐标是否在圆内的正方形内,这是四个快速比较,这覆盖了 50% 的内部点,但明显减慢了另外50%的点。要查看它是否有所改善,您必须对其进行测试。With regard to your update, it all looks good.
You may get a slight performance upgrade by reversing the order of the two
if()
parameters so thatmyHover != "transition1"
is first. The&&
is short-circuit, so ifmyHover != "transition1"
is false, the expensive circle inclusion check does not need to be called.Also on the
else if()
might be worth having some variable set to something that says you have already set the cursor to stop that getting called continuously.Looking at the
SimpleCircle
class, the only expensive operations it makes are two power calls and a square root (Math.pow() x 2 + Math.sqrt()
). Whether or not it is worth trying to get that any faster is debatable, only optimisation I can think of there is to check if the coordinates are within the square within the circle which is four quick comparisons, this covers 50% of the interior points, but obviously slows down the other 50% of points. To see if it improved matters you would have to test it.