目标是在div标签中显示一些文本(html),对其他元素触发的鼠标过/关事件具有淡入/淡出效果。
我使用了Animate.css解决方案并遇到了很多问题,特别是当元素快速连续盘旋时。
当我尝试构建一个更简单的模型时,不使用jQuery,与原始解决方案不同,代码行为的一部分对我来说是莫名其妙的 - 请参阅下面的示例。它按预期工作,但如果省略以下行document.getElementById("info").innerHTML="animate.css has ended; was triggered by "+e.target.id+" on "+e.type+" event.";
,则无法识别触发动画功能的事件,并且文本隐藏在mouseOver上。由于将元素的innerHTML更改为我的理解与animationend事件无关,希望有人可以解释此代码行为。
// (e), event is used to differentiate between mouseOver and mouseOut
function animate(e){
// start mesage
document.getElementById("info").innerHTML=e.target.id+" fired "+e.type+"; animate.css is starting...";
// setting animation type based on the triggering event
var animation = "animated fadeIn";
if (e.type=="mouseout"){
animation = "animated fadeOut";
}
// triggering animation by applying the animation classes
document.getElementById("info").setAttribute("class", animation);
// setting animation end callback
this.addEventListener("animationend", function(){
// end message. If the line below is commented, the message is deleted regardless of the event that fired it (it is expected to be deleted on mouseOut only)
document.getElementById("info").innerHTML="animate.css has ended; was triggered by "+e.target.id+" on "+e.type+" event.";
// removing (regenerating) the animation classes
document.getElementById("info").removeAttribute("class");
// deletes the message on mouseOut
if (e.type=="mouseout"){
document.getElementById("info").innerHTML="null";
}
});
}
// all svg path elements will trigger the animate(event) function on mouseOver and mouseOut
var petals = document.querySelectorAll("path");
for(i=0;i<petals.length; i++){
//changes the default mouse cursor into a hand
petals[i].style="cursor: pointer;";
//mouseOver
petals[i].addEventListener("mouseover", function (event){
animate(event);
});
//mouseOut
petals[i].addEventListener("mouseout", function (event){
animate(event);
});
}
<style>
html, body {
height: 100%;
margin: 0px;
}
#info {
height: 15%;
/* background-color: darkgreen;
color: gainsboro;*/
font-family: monospace;
font-size: 5.5vh;
padding: 2%;
}
/* animate.css: */
.animated {
animation-duration: 2s;
animation-fill-mode: both;
}
.animated.fadeOut {
animation-duration: 3s;
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
.fadeOut {
animation-name: fadeOut;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fadeIn {
animation-name: fadeIn;
}
</style>
<div id="info"> info </div>
<div style="height: 70%; background-color:papayawhip; padding: 1.5%;">
<svg width="100%" height="100%" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 318.3 258.1" style="enable-background:new 0 0 318.3 258.1;" xml:space="preserve">
<style type="text/css">
.darkred{
fill: darkred;
stroke-width: 1;
}
.darkred:hover{
fill: red;
stroke: black;
}
.red{
fill: red;
}
.red:hover {
fill: orange;
stroke: black;
}
.orange{
fill: orange;
}
.orange:hover {
fill: yellow;
stroke: black;
}
</style>
<path id="petal-1" class="darkred" d="M159.1,1c53.3,42.7,53.3,85.3,0,128V1z"/>
<path id="petal-2" class="orange" d="M213.8,8.8c31.9,54.7,13.6,94.8-54.7,120.3L213.8,8.8z"/>
<path id="petal-3" class="red" d="M262,31c6.6,60.1-27.7,92.8-102.8,98.1L262,31z"/>
<path id="petal-4" class="darkred" d="M297.7,65c-19.5,58.3-65.7,79.6-138.6,64L297.7,65z"/>
<path id="petal-5" class="orange" d="M316.7,106.8c-43.3,49.4-95.8,56.8-157.6,22.2L316.7,106.8z"/>
<path id="petal-6" class="red" d="M316.7,151.3c-61.8,34.6-114.3,27.2-157.6-22.2L316.7,151.3z"/>
<path id="petal-7" class="darkred" d="M297.7,193c-72.9,15.6-119-5.7-138.6-64L297.7,193z"/>
<path id="petal-8" class="orange" d="M262,227.1c-75.1-5.3-109.4-37.9-102.8-98.1L262,227.1z"/>
<path id="petal-9" class="red" d="M213.8,249.3c-68.4-25.5-86.6-65.6-54.7-120.3L213.8,249.3z"/>
<path id="petal-10" class="darkred" d="M159.1,257c-53.3-42.7-53.3-85.3,0-128V257z"/>
<path id="petal-11" class="orange" d="M104.4,249.3c-31.9-54.7-13.6-94.8,54.7-120.3L104.4,249.3z"/>
<path id="petal-12" class="red" d="M56.3,227.1C49.7,167,84,134.3,159.1,129L56.3,227.1z"/>
<path id="petal-13" class="darkred" d="M20.5,193c19.5-58.3,65.7-79.6,138.6-64L20.5,193z"/>
<path id="petal-14" class="orange" d="M1.5,151.3c43.3-49.4,95.8-56.8,157.6-22.2L1.5,151.3z"/>
<path id="petal-15" class="red" d="M1.5,106.8C63.3,72.2,115.8,79.6,159.1,129L1.5,106.8z"/>
<path id="petal-16" class="darkred" d="M20.5,65c72.9-15.6,119,5.7,138.6,64L20.5,65z"/>
<path id="petal-17" class="orange" d="M56.3,31c75.1,5.3,109.4,37.9,102.8,98.1L56.3,31z"/>
<path id="petal-18" class="red" d="M104.4,8.8C172.7,34.3,191,74.4,159.1,129L104.4,8.8z"/>
</svg>
</div>
答案 0 :(得分:1)
您正在观察的行为不是由未被识别的事件引起的,而是由于回调函数的执行顺序。
让我试着解释一下......
当你注释掉document.getElementById("info").innerHTML="animate.css has ended; was triggered by "+e.target.id+" on "+e.type+" event.";
行时,这就是你得到的:
对于每个mouseover
和mouseout
事件,您都在调用两个函数:
animate(e)
,在div中显示一些文字,然后启动动画。function()
在animationend
上执行,会检查e.type == 'mouseout'
。如果是,它会将div中的文本更改为&#39; null&#39;否则,它将不会更改文本。 (如果你注释掉上面提到的那一行。)然而,这很重要,第一个函数在触发事件时立即调用,第二个函数是仅在动画结束后调用的回调函数。
当你将鼠标悬停在花瓣A上并快速跳到花瓣B时,你可能没有意识到,但实际上发生了三个事件:
mouseover
事件mouseout
事件mouseovoer
事件这些事件中的每一个都将最终调用两个函数,但是,因为第二个函数仅在动画完成后调用,所以函数按以下顺序执行:
mouseover
(花瓣A)致电animate(e)
mouseout
(花瓣A)致电aminate(e)
mouseover
(花瓣B)致电animate(e)
animationend
(花瓣A)的mouseover
致电匿名function()
animationend
(花瓣A)的mouseout
致电匿名function()
animationend
(花瓣B)的mouseover
致电匿名function()
让我们来看看这会如何影响div中的文字:
在步骤1-3 ,div会显示事件目标ID,事件类型,并且&#39; animate.css正在开始......&#39;。
第4步 div中的任何内容都不会更改,因为事件类型为mouseover
。 div将继续显示事件目标ID,事件类型,并且&#39; animate.css正在按预期开始......&#39;
在步骤5 ,div中的文字将更改为&#39; null&#39;,因为动画是由mouseout
事件触发的。
在第6步时,div中的任何内容都不会更改,因为事件类型为mouseover
。因此div将继续显示&#39; null&#39; ...
为了证明这一点,您可以将事件目标ID添加到文本中,并且您将看到它是前一个导致&#39; null&#39;要显示,而不是你正在盘旋的花瓣。或者,如果if {} else {}
不等于animationend
,请使用e.type
更改mouseout
上div中的文字,并且您会发现这里没有混淆它是哪个事件。
if (e.type=="mouseout"){
document.getElementById("info").innerHTML="null " + e.target.id;
} else {
document.getElementById("info").innerHTML="This is the animationend of a " + e.type + " event";
}
除非您明确删除,否则不会删除添加到DOM的事件侦听器,或者使用once: true
选项添加它。
由于您要在每个animationend
和mouseover
事件中添加一个事件监听器来监听mouseout
,而不会将其删除,因此您最终将会触发数十个触发该事件的事件监听器animationend
上的回调函数。
通过将once: true
选项添加为addEventListener()
的参数,可以轻松解决此问题。一旦调用回调函数,这将自动删除侦听器。
function animate(e){
document.getElementById("info").innerHTML=e.target.id+" fired "+e.type+"; animate.css is starting...";
var animation = "animated fadeIn";
if (e.type=="mouseout"){
animation = "animated fadeOut";
}
document.getElementById("info").setAttribute("class", animation);
this.addEventListener("animationend", function() {
document.getElementById("info").removeAttribute("class");
if (e.type=="mouseout"){
document.getElementById("info").innerHTML="null ";
}
}, {once: true}); // Add this option to automatically remove event listener once invoked
}
答案 1 :(得分:0)
Chava G,非常感谢您抽出宝贵时间并详细分析代码的实施方式。在绞尽脑汁之后,我想我有了这个主意......
我知道addEventListener方法的“once”选项,但不知道如何实现它。我不知道相同的事件监听器被附加而不是替换,这解释了性能问题和开发人员工具中的一些代码重复消息,我不知道如何解决。除了this.addEventListener(“animationend”,function())之外,这似乎引用了窗口对象......
如何将animationend事件仅附加到info div而不是尝试删除它?顺便说一下,如果交替动画具有不同的名称,例如animationIn和animationOut,不需要清除动画类的animationend事件,如下面的项目版本所示。然而,在Firefox中,鼠标悬停动画在悬停在多个元素上时仅应用一次,而在IE中,每个元素都是动画的。这是一个特定于浏览器的问题,还是我的编码又出现了问题?
// (e), event is used to differentiate between mouseOver and mouseOut
function animate(e){
// start mesage
document.getElementById("info").innerHTML=e.target.id+" fired "+e.type+"; animate.css is starting...";
// setting animation type based on the triggering event
var animation = "animated ";
if (e.type=="mouseout"){
animation += animationOut;
}
else{
animation += animationIn;
}
// triggering animation by applying the animation classes
document.getElementById("info").setAttribute("class", animation);
}
// all svg path elements will trigger the animate(event) function on mouseOver and mouseOut
var petals = document.querySelectorAll("path");
for(i=0;i<petals.length; i++){
//changes the default mouse cursor into a hand
petals[i].setAttribute("style", "cursor: pointer;");
//mouseOver
petals[i].addEventListener("mouseover", function (event){
animate(event);
});
//mouseOut
petals[i].addEventListener("mouseout", function (event){
animate(event);
});
}
html, body {
font-family: monospace;
height: 100%;
margin: 0px;
}
#container-info {
position: relative;
overflow: hidden;
}
#info {
height: 10%;
/* background-color: darkgreen;
color: gainsboro;*/
font-size: 5.5vmin;
padding: 2%;
}
#blossom {
height: 65%;
background-color: papayawhip;
padding: 1.5%;
}
.transitions-menu {
display: inline-block;
padding: 0.5%;
background-color: papayawhip;
font-size: 2vw;
color: darkred;
border: 1px solid darkred;
}
select {
background-color: BurlyWood;
font-family: monospace;
font-size: 1em;
color: darkred;
}
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.5.2/animate.min.css">
<div class="transitions-menu">animationIn =
<select onchange = "animationIn = this.value; animationOut = animationIn.replace(/In/i, 'Out'); document.getElementsByName('out')[0].selectedIndex = this.selectedIndex;">
<script type="text/javascript">
var animationIn = "fadeIn";
animations = [
"bounceIn",
"bounceInDown",
"bounceInLeft",
"bounceInRight",
"bounceInUp",
"fadeIn",
"fadeInDown",
"fadeInDownBig",
"fadeInLeft",
"fadeInLeftBig",
"fadeInRight",
"fadeInRightBig",
"fadeInUp",
"fadeInUpBig",
"flipInX",
"flipInY",
"lightSpeedIn",
"rollIn",
"rotateIn",
"rotateInDownLeft",
"rotateInDownRight",
"rotateInUpLeft",
"rotateInUpRight",
"slideInDown",
"slideInLeft",
"slideInRight",
"slideInUp",
"zoomIn",
"zoomInDown",
"zoomInLeft",
"zoomInRight",
"zoomInUp",
//////////////////////////////////////
"bounce",
"flash",
"headShake",
"hinge",
// has no Out equivalent "jackInTheBox",
"jello",
"pulse",
"rubberBand",
"shake",
"swing",
"tada",
"wobble"
];
for (i=0; i<animations.length;i++){
if (animations[i] != animationIn){
document.write('<option value="' + animations[i]+ '">' + animations[i]+ '</option>\n');
}
else {
document.write('<option value="' + animations[i]+ '" selected>' + animations[i]+ '</option>\n');
}
}
</script>
</select>
</div>
<div class="transitions-menu">animationOut =
<select name="out" onchange = "animationOut = this.value">
<script type="text/javascript">
// var animationOut = "fadeOutRight";
var animationOut = animationIn.replace(/In/, "Out");
for (i=0; i<animations.length;i++){
var optName = animations[i].replace(/In/, "Out");
if (animations[i] != animationIn){
document.write('<option value="' + optName + '">' + optName + '</option>\n');
}
else {
document.write('<option value="' + optName + '" selected>' + optName + '</option>\n');
}
}
</script>
</select>
</div>
<div id="container-info">
<div id="info"> info </div>
</div>
<div id="blossom">
<svg width="100%" height="100%" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 318.3 258.1" style="enable-background:new 0 0 318.3 258.1;" xml:space="preserve">
<style type="text/css">
.darkred{
fill: darkred;
stroke-width: 1;
}
.darkred:hover{
fill: red;
stroke: black;
}
.red{
fill: red;
}
.red:hover {
fill: orange;
stroke: black;
}
.orange{
fill: orange;
}
.orange:hover {
fill: yellow;
stroke: black;
}
</style>
<path id="petal-1" class="darkred" d="M159.1,1c53.3,42.7,53.3,85.3,0,128V1z"/>
<path id="petal-2" class="orange" d="M213.8,8.8c31.9,54.7,13.6,94.8-54.7,120.3L213.8,8.8z"/>
<path id="petal-3" class="red" d="M262,31c6.6,60.1-27.7,92.8-102.8,98.1L262,31z"/>
<path id="petal-4" class="darkred" d="M297.7,65c-19.5,58.3-65.7,79.6-138.6,64L297.7,65z"/>
<path id="petal-5" class="orange" d="M316.7,106.8c-43.3,49.4-95.8,56.8-157.6,22.2L316.7,106.8z"/>
<path id="petal-6" class="red" d="M316.7,151.3c-61.8,34.6-114.3,27.2-157.6-22.2L316.7,151.3z"/>
<path id="petal-7" class="darkred" d="M297.7,193c-72.9,15.6-119-5.7-138.6-64L297.7,193z"/>
<path id="petal-8" class="orange" d="M262,227.1c-75.1-5.3-109.4-37.9-102.8-98.1L262,227.1z"/>
<path id="petal-9" class="red" d="M213.8,249.3c-68.4-25.5-86.6-65.6-54.7-120.3L213.8,249.3z"/>
<path id="petal-10" class="darkred" d="M159.1,257c-53.3-42.7-53.3-85.3,0-128V257z"/>
<path id="petal-11" class="orange" d="M104.4,249.3c-31.9-54.7-13.6-94.8,54.7-120.3L104.4,249.3z"/>
<path id="petal-12" class="red" d="M56.3,227.1C49.7,167,84,134.3,159.1,129L56.3,227.1z"/>
<path id="petal-13" class="darkred" d="M20.5,193c19.5-58.3,65.7-79.6,138.6-64L20.5,193z"/>
<path id="petal-14" class="orange" d="M1.5,151.3c43.3-49.4,95.8-56.8,157.6-22.2L1.5,151.3z"/>
<path id="petal-15" class="red" d="M1.5,106.8C63.3,72.2,115.8,79.6,159.1,129L1.5,106.8z"/>
<path id="petal-16" class="darkred" d="M20.5,65c72.9-15.6,119,5.7,138.6,64L20.5,65z"/>
<path id="petal-17" class="orange" d="M56.3,31c75.1,5.3,109.4,37.9,102.8,98.1L56.3,31z"/>
<path id="petal-18" class="red" d="M104.4,8.8C172.7,34.3,191,74.4,159.1,129L104.4,8.8z"/>
</svg>
</div>