javascript - Text Fade Effect with Animate.css - unexplained behavior -
the goal display text (html) in div tag fade in/ fade out effect on mouse over/ out events triggered element(s). used animate.css solution , came across multitude of problems, when elements hovered in rapid succession. when tried build simpler model, without resorting jquery, unlike original solution, 1 part of code behavior inexplicable me - please see below example. works expected, if following line document.getelementbyid("info").innerhtml="animate.css has ended; triggered "+e.target.id+" on "+e.type+" event.";
omitted, events triggered animation function not recognized , text hides on mouseover. changing innerhtml of element understanding has nothing animationend event, hope can explain code behavior.
// (e), event used differentiate between mouseover , mouseout function animate(e){ // start mesage document.getelementbyid("info").innerhtml=e.target.id+" fired "+e.type+"; animate.css starting..."; // setting animation type based on triggering event var animation = "animated fadein"; if (e.type=="mouseout"){ animation = "animated fadeout"; } // triggering animation applying animation classes document.getelementbyid("info").setattribute("class", animation); // setting animation end callback this.addeventlistener("animationend", function(){ // end message. if line below commented, message deleted regardless of event fired (it expected deleted on mouseout only) document.getelementbyid("info").innerhtml="animate.css has ended; triggered "+e.target.id+" on "+e.type+" event."; // removing (regenerating) animation classes document.getelementbyid("info").removeattribute("class"); // deletes message on mouseout if (e.type=="mouseout"){ document.getelementbyid("info").innerhtml="null"; } }); } // svg path elements trigger animate(event) function on mouseover , mouseout var petals = document.queryselectorall("path"); for(i=0;i<petals.length; i++){ //changes default mouse cursor 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 { { opacity: 1; } { opacity: 0; } } .fadeout { animation-name: fadeout; } @keyframes fadein { { opacity: 0; } { 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>
the behavior observing not caused events not being recognized, rather because of order in callback functions being executed.
let me try explain this...
when comment out line document.getelementbyid("info").innerhtml="animate.css has ended; triggered "+e.target.id+" on "+e.type+" event.";
, get:
the setup
for every mouseover
, mouseout
event, calling two functions:
animate(e)
, displays text in div, , starts animation.- anonymous
function()
executed onanimationend
, check ife.type == 'mouseout'
. if is, change text in div 'null', otherwise, not change text @ all. (if comment out line mentioned above.)
however, , important, first function called event triggered, , second 1 callback function called after animation has ended.
hovering on elements in rapid succession
when hover on petal a, , jump petal b, may not have realize, there three events happening:
- there
mouseover
event on petal a - there
mouseout
event on petal a - there
mouseovoer
event on petal b
each of these events, end calling 2 functions, however, since second function called once animation complete, functions executed in following order:
mouseover
(petal a) callsanimate(e)
mouseout
(petal a) callsaminate(e)
mouseover
(petal b) callsanimate(e)
animationend
mouseover
(petal a) calls anonymousfunction()
animationend
mouseout
(petal a) calls anonymousfunction()
animationend
mouseover
(petal b) calls anonymousfunction()
let's examine how effects text in div:
at step 1-3 div display event target id, event type, , 'animate.css starting...'.
at step 4 nothing in div change, since event type
mouseover
. div continue display event target id, event type, , 'animate.css starting...', expected.at step 5 text in div change 'null', because animation triggered
mouseout
event.at step 6, again, nothing in div change, since event type
mouseover
. div continue display 'null'...
proof of concept
to prove this, can either add event target id text, , see previous petal caused 'null' displayed, , not petal hovering over. or, use if {} else {}
, change text in div on animationend
if e.type
not equal mouseout
, , you'll see there no confusion here on event was.
if (e.type=="mouseout"){ document.getelementbyid("info").innerhtml="null " + e.target.id; } else { document.getelementbyid("info").innerhtml="this animationend of " + e.type + " event"; }
important note:
an event listener added dom not removed, unless explicitly remove it, or add once: true
option.
since adding event listener listen animationend
on every mouseover
, mouseout
event, without ever removing it, end dozens of event listeners triggering same callback function on animationend
.
this can fixed adding once: true
option argument addeventlistener()
. automatically remove listener callback function invoked.
function animate(e){ document.getelementbyid("info").innerhtml=e.target.id+" fired "+e.type+"; animate.css 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 option automatically remove event listener once invoked }
Comments
Post a Comment