悬停隐藏元素会在不久之后重播隐藏动画
Posted
技术标签:
【中文标题】悬停隐藏元素会在不久之后重播隐藏动画【英文标题】:Hovering a hiding element replays the hide animation shortly after 【发布时间】:2012-03-13 23:10:30 【问题描述】:我有 2 个元素彼此相邻,都是绝对定位的。
<div class="vizual">
<h1 class="typo">...</h1>
<a href="#" class="typo">...</a>
</div>
当我将鼠标悬停在第一个元素上时,另一个元素会出现在它旁边。有一些效果和计时器正在运行。
function hoverTransfer(trigger,content)
var t;
$(trigger).hover(
function()
clearTimeout(t);
if ($(content).css("display") == "none")
$(content).show('slide', direction: 'left', 500);
, function()
t = setTimeout(function() $(content).hide('slide', direction: 'left', 500), 550);
);
$(content).hover(
function()
clearTimeout(t);
, function()
t = setTimeout(function() $(content).hide('slide', direction: 'left', 500), 550);
);
;
它应该以某种方式工作,当我将鼠标悬停在两个元素之一上时,第二个元素保持显示。当我将鼠标移出时,它会在一段时间后滑回。
编辑:如果我在隐藏第二个元素时将鼠标悬停在其中一个元素上,它应该滑回全宽。但是我也不能生产...
问题 - 它的行为方式也是不受欢迎的: 当我将鼠标悬停在这些元素之一的进出而第二个元素隐藏时,它会在完成后不久再次重播隐藏动画。
我尝试了很多不同的“解决方案”(检查元素是否动画,尝试 .stop() 等,但我永远无法产生所需的功能。
【问题讨论】:
如果您在 jsFiddle 中重现此内容,我认为人们帮助您会容易得多。 :) 另外,你想要的确切效果是什么?到目前为止,您真正提到的只是它没有按您希望的方式工作。 jsfiddle.net/sgrxH 将鼠标悬停在红色框上,将鼠标移出元素,当绿色框滑回时,将鼠标移到其中一个元素上(不要按住它,只需当绿色框向后滑动时穿过它)。 【参考方案1】:说明
好的,我已经拟定了我认为您所要求的内容。如果这不是您所要求的,希望您或其他人可以从中学到一些东西。 :)
-
开始布局
用户将鼠标悬停在元素 1 上,元素 2 随即弹出并开始滑动
此时,用户在元素之间悬停,不应发生重置
用户从其中一个元素(在我的示例中为元素 1)悬停在外面
鼠标未在其中一个元素上停留 n 秒,应该像在 2 中一样滑动。但反向。
我发现如果你先概述需要做什么,就更容易知道需要做什么。
通过这些步骤,我们现在可以定义我们需要什么:
-
当
n
秒过去时,检查鼠标在执行“反向动画”的元素之外多长时间的计时器
MouseIn、MouseOut 事件清除计时器,因此当用户仍悬停其中一个元素时它不会执行反向动画
我们需要为每个组实例设置唯一的计时器,我称之为实例化。含义:我们希望能够在超过 1 个包含 2 个元素的块上执行此操作
解决方案
首先,here's a JSFiddle 供您使用 (here's one without comments)。希望有足够多的 cmets 帮助您度过难关。
当然,这是代码。
//default variables
var Distance = 300; //px
var BetweenOffset = 10; //px
var MouseOut = 550; //ms
var AnimationTime = 500; //ms
var Timers = new Array();
$(document).ready(function()
//this is just to add the default distance. I didn't specify it in the CSS, but you can do it just as well
$("div.container div.element_2").css("left", Distance);
//adds an attribute "unique-id" with a number, so that the timer can be associated with an element. This is necessary to be able to clear the timer, and is the basics in "instantiation 101"
$("div.container").each(function(index, parent)
$(parent).attr("unique-id", index);
);
//here's were all the magic happens
$("div.container div.element_1, div.container div.element_2").mouseenter(function(e)
//define some local variables
var parent = $(this).parent();
var id = parent.attr("unique-id");
var element1 = parent.children(".element_1");
var element2 = parent.children(".element_2");
var destination = element1.width()+BetweenOffset;
//if element2 isn't visible or is being animated, we're going to stop whatever it's doing and do a beginning animation
if(!element2.is(":visible") || element2.is(":animated") )
element2.stop(true).show().animate(
left: destination,
opacity: 1
,
AnimationTime,
"swing"
);
//then we're gonna clear the timer associated with this parent
Timers[id]= clearTimeout(Timers[id]);
).mouseleave(function(e)
var parent = $(this).parent();
var id = parent.attr("unique-id");
var element1 = parent.children(".element_1");
var element2 = parent.children(".element_2");
//here we set the timer using an anonymous function
Timers[id] = setTimeout(function()
//Only animate if it's already showing
if(element2.is(":visible"))
//stop whatever it's doing and remove the animation queue
element2.stop(true).animate(
"left": Distance,
opacity: 0
,
AnimationTime,
"swing",
function()
//here we make sure it's not being displayed
element2.css("display", "none");
);
, MouseOut);
);
);
<div class="container">
<div class='element_1'>Element 1</div>
<div class='element_2'>Element 2</div>
</div>
<div class="container">
<div class='element_1'>Element 1</div>
<div class='element_2'>Element 2</div>
</div>
<div class="container">
<div class='element_1'>Element 1</div>
<div class='element_2'>Element 2</div>
</div>
<div class="container">
<div class='element_1'>Element 1</div>
<div class='element_2'>Element 2</div>
</div>
<div class="container">
<div class='element_1'>Element 1</div>
<div class='element_2'>Element 2</div>
</div>
CSS
.container
position: relative;
height: 50px;
margin-top: 20px;
.element_1, .element_2
position: absolute;
height: 50px;
left: 0px;
top: 0px;
.element_1
border: 1px solid blue;
.element_2
border: 1px solid red;
display: none;
参考文献
对我使用的函数的一些参考
.parent() .children() .stop() .animate() .mouseenter() .mouseleave() .attr() setTimeout() & clearTimeout() What is instantiation?最后的想法
我添加了一些很酷的不透明度过渡,这不是必需的,但是……嗯。 希望这会对您有所帮助,可能有替代我给您的方法,但这是我的解决方法。
编辑
经过简短讨论后,OT 通知了我他的 JSFiddle。我看了看,this is what I got。剩下的唯一问题是它在动画时没有动画,但这是一个没有多少用户注意到的小问题。
【讨论】:
哇,我真的没想到有人会走这么远来提供帮助!在 OP 的 cmets 中,我发布了一个更清晰的 jsfiddle 链接,但即使没有它,您的解决方案也非常接近......第二个元素应该从第一个元素出现。 1 页上只有 1 个实例,因此在这种情况下不需要这些变量......我会尝试根据我的需要对其进行修改,然后告诉你它是如何进行的。无论如何+1,谢谢! @SqueezCZ 我的例子应该可以解决你的问题。查看计时器以及如何处理它们。我没有注意到你的jsfiddle,我会看看它。此外,每个帖子的顶部都会给出+1,并通过单击同一位置的绿色复选标志给出正确答案。感谢代表。 :) @ShadowScripter - 实际上,我的声誉似乎太低了,无法给你 +1。当我到达那里时,我会这样做!无论如何,您认为您可以在查看 jsfiddle 后修改答案吗?我不需要在更多情况下使用它,这样可以更容易地重写它。我在脚本方面不是“新手”,但我认为我无法修改你的脚本来为我工作,我还没有达到那个水平,但我害怕......我会很感激很多 @SqueezCZ 好的,我已经用你的 JSFiddle 版本更新了帖子。 @ShadowScripter - 差不多了!我们都在我们的编辑信息中声明了“在动画期间返回全宽”功能尚未创建。你认为有一些不太复杂的解决方案吗?以上是关于悬停隐藏元素会在不久之后重播隐藏动画的主要内容,如果未能解决你的问题,请参考以下文章