Patrick Andrieu: Fade-Effekt bei Mouseover... wie und wo merken?

Hallo alle!

http://www.atomic-eggs.com/z_testdir/scripts/javascript/hoverfade/hoverfade.html

Das Skript auf o.g. Seite faded ein Bild unterhalb des gelben Vierecks ein beim Drüberfahren mit der Maus und wieder aus, wenn der Zeiger das Viereck verläßt. Soweit, sogut, wenn man das gediegen macht.

Hektiker hingegen werden beobachten, dass wenn man sehr schnell mit der Maus über das Viereck hovert, das Textbild unten nur flackert und nicht mehr verschwindet, auch wenn der Zeiger schon weit weg vom Viereck ist.

Eine Idee, wo ich ansetzen soll?

Viele Grüße aus Frankfurt/Main,
Patrick

--
_ - jenseits vom delirium - _

   Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
  1. Eine Idee, wo ich ansetzen soll?

    Schuss aus der Hüfte:
    Wenn man mit der Maus den Bereich verlässt, nimmt die Opazität von 100 bis 0 ab oder vom derzeit _aktuellen Wert?
    Vice versa beim FadeIn

    gruß, bb

  2. Hi Patrick,

    Eine Idee, wo ich ansetzen soll?

    Du lässt anonyme timeouts laufen, so dass mehrere gleichzeitig angestossen werden können und sich überlagern. Ich würde auf jedenfall immer mit einem handler arbeiten (foo = setTimeout()), den ich jedesmal cleare (clearTimeout(foo)) bevor ich einen neue Anweisung anstosse. Ältere Browser mögen teils auch einen flag, denn ich hin und herschalte, so dass ich immer weiss, ob grade ein timeout läuft.

    Gruesse, Joachim

    --
    Am Ende wird alles gut.
  3. Lieber Patrick,

    in meinem Fader-Framework habe ich einen Mechanismus implementiert, der einen Fading-Vorgang "unterbrechungssicher" macht. Schau's Dir doch einmal an. Stichwort "this.fading"

    Liebe Grüße,

    Felix Riesterer.

    --
    ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
    1. Hallo Felix!

      Ich antworte hier auch an Joachim und benben. Zunächst: Dieser Schriftzug, der (als Bild) eingeblendet werden soll, wird später eine Art Ergänzungsinfo zu einem Logo (dem Viereck im Beispiel). Es soll auf jeden Fall bis zum Ende eingeblendet werden, nur halt wieder verschwinden, wenn der Mauszeiger nicht mehr über das Viereck »steht«. Sprich: Einmal Hovern, egal wie schnell oder langsam, soll das Bild bis zur vollen Sichtbarkeit gezeigt werden. Das Faden soll (@Felix) also nicht unterbrochen werden.

      Im Moment passiert folgendes: Beim schnellen Hovern wird der Timeout immer wieder neu angestoßen, daher das Flackern. Zudem wird fade.hide() nicht mehr ausgeführt. Der Ansatz von Joachim ist daher eine Idee, die ich im Laufe des Nachmittags probieren werde.

      @benben:

      Meine Versuche, mir den Grad der Opacity zu merken, sind bisher dran gescheitert, dass ich beim allerersten Hovern logischeerweise »undefined« erhalten, später immer »1«.

      Viele Grüße aus Frankfurt/Main,
      Patrick

      --
      _ - jenseits vom delirium - _

         Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
      J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
      1. Im Moment passiert folgendes: Beim schnellen Hovern wird der Timeout immer wieder neu angestoßen, daher das Flackern. Zudem wird fade.hide() nicht mehr ausgeführt. Der Ansatz von Joachim ist daher eine Idee, die ich im Laufe des Nachmittags probieren werde.

        Wieso setzt du nicht einfach einen Flag, der anzeigt, dass dein Objekt beschäfigt ist und unterbindest damit alle Events. Das dürfte das übliche Vorgehen für sowas sein. Dazu musst du dein Skript aber natürlich einen Tick komplexer machen, als es jetzt ist.

        Struppi.

      2. Es soll auf jeden Fall bis zum Ende eingeblendet werden, nur halt wieder verschwinden, wenn der Mauszeiger nicht mehr über das Viereck »steht«. Sprich: Einmal Hovern, egal wie schnell oder langsam, soll das Bild bis zur vollen Sichtbarkeit gezeigt werden.

        Also einblenden beim hovern, bis zum Ende. ausblenden beim mouseout zu bis zum Ende. Und wenn die Mouse dann wieder das einblenden anstößt und dann wieder weg geht?
        Du kannst dieses Spielchen bis zum Ende betreiben und hast eine endlose Rekursion oder eine Unterbrechung in dem Ablauf. Also:

        1. mouseover
        2. einblenden. währenddessen -> mouseout -> einblenden geht weiter
        3. ausblenden. währenddessen -> mouseover -> ausblenden geht weiter?

        Im Moment passiert folgendes: Beim schnellen Hovern wird der Timeout immer wieder neu angestoßen,

        Dein Ansatz ist nicht besonders elegant und widerspricht auch vielen Programmierparadigmen. Du verwendest hier ein Objekt, das keinen Sinn macht. Du erzeugst einfach unzählige timeouts, anstatt den Ablauf zu steuern.

        Ich würd' das in etwa so umsetzen:

        var fade = new function() {  
        	var aktiv = false;  
        	var node;  
        	var o = 0;  
        	var inout = true;  
        	var	callback;  
        	function fade_func() {  
        		node.style.filter = 'Alpha(opacity=' + o + ')';  
        		node.style.opacity = o / 100;  
        		o += inout ? 1 : -1;  
        		if( (inout && o > 100) || (!inout && o < 0)){  
        			aktiv = false;  
        			if(callback) callback();  
        			callback = null;  
        		} else {  
        			window.setTimeout(fade_func, 10);  
        		}  
        	};  
        	  
        	this.init = function(action, fade_node) {  
        		action  =  document.getElementById(action);  
        		if(!action) return;  
        		  
        		action.onmouseover = function() {  
        			if(!aktiv){  
        				inout = true;  
        				aktiv = true;  
        				fade_func();  
        			}  
        		};  
        		action.onmouseout = function() {  
        			if(aktiv) {  
        				callback = function() {  
        					aktiv = true;  
        					inout = false;  
        					fade_func();  
        				};  
        			} else {  
        				aktiv = true;  
        				inout = false;  
        				fade_func();  
        			}  
        		};  
        		node =  document.getElementById(fade_node);  
        	};  
        };  
        window.onload = function() {fade.init('foo', 'fadein');}  
        
        

        Struppi.

        1. Hallo Struppi!

          1. mouseover
          2. einblenden. währenddessen -> mouseout -> einblenden geht weiter
          3. ausblenden. währenddessen -> mouseover -> ausblenden geht weiter?

          In etwa. An sich könnte das Ausblenden unterbrochen werden, da muss ich mal schauen.

          Dein Ansatz ist nicht besonders elegant und widerspricht auch vielen Programmierparadigmen.

          Ich habe nie behauptet, dass ich ein Programmierer bin ;) Aber inwiefern?

          Ich würd' das in etwa so umsetzen:

          var fade = new function() {

          var aktiv = false;
          var node;
          var o = 0;
          var inout = true;
          var callback;
          function fade_func() {
          node.style.filter = 'Alpha(opacity=' + o + ')';
          node.style.opacity = o / 100;
          o += inout ? 1 : -1;
          if( (inout && o > 100) || (!inout && o < 0)){
          aktiv = false;
          if(callback) callback();
          callback = null;
          } else {
          window.setTimeout(fade_func, 10);
          }
          };

          this.init = function(action, fade_node) {
          action  =  document.getElementById(action);
          if(!action) return;

            action.onmouseover = function() {  
            	if(!aktiv){  
            		inout = true;  
            		aktiv = true;  
            		fade_func();  
            	}  
            };  
            action.onmouseout = function() {  
            	if(aktiv) {  
            		callback = function() {  
            			aktiv = true;  
            			inout = false;  
            			fade_func();  
            		};  
            	} else {  
            		aktiv = true;  
            		inout = false;  
            		fade_func();  
            	}  
            };  
            node =  document.getElementById(fade_node);  
          

          };
          };
          window.onload = function() {fade.init('foo', 'fadein');}

            
          Danke, werde das mal testen. Ob ich heute dazu komme, weiß ich allerdings noch nicht. Im Moment blicke ich hier nocht nicht durch, was wozu zuständig ist, dass werde ich erst am lebenden Beispiel sehen :)  
            
            
          Viele Grüße aus Frankfurt/Main,  
          Patrick
          
          -- 
          \_ - jenseits vom delirium - \_  
          ![](http://www.atomic-eggs.com/fuernA.jpg)  
             [Diblom](http://www.atomic-eggs.com/pics/diblom.png)   [[link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash](http://www.atomic-eggs.com/)]  
          [J'ai 10 ans!](http://www.atomic-eggs.com/wae/wae_10.shtml#a5) | Achtung [Agentur](http://www.atomic-eggs.com/cwi/cwi_5.shtml#a5)! | Nichts ist unmöglich? [Doch!](http://www.atomic-eggs.com/cwi/cwi_4.shtml) | [Heute](http://www.atomic-eggs.com/cgi-bin/date_today.pl) schon ge[gök](http://goek.atomic-eggs.com/goek_goek.html)t?
          
        2. Hallo Struppi!

          und hast eine endlose Rekursion oder eine Unterbrechung in dem Ablauf. Also:
          Ich würd' das in etwa so umsetzen:

          ~~~javascript

            	if(callback) callback();  
          

            
          Diese Zeile verursacht in der Tat einen stack overflow (so der IE) oder »too much recursion«, so Firefox.  
            
          Ich habe mich jetzt dazu entschieden, dass der Schriftzug eingeblendet wird beim Hovern. Wenn einer zu schnell das Viereck verläßt, bleibt es eben stehen. Schließlich soll die Info ja gesehen werden[1]. Beim langsamen Hovern verschwindet es wie gehabt.  
            
          [1] Außerdem kann ich das für andere Effekte nutzen.  
            
          Viele Grüße aus Frankfurt/Main,  
          Patrick
          
          -- 
          \_ - jenseits vom delirium - \_  
          ![](http://www.atomic-eggs.com/fuernA.jpg)  
             [Diblom](http://www.atomic-eggs.com/pics/diblom.png)   [[link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash](http://www.atomic-eggs.com/)]  
          [J'ai 10 ans!](http://www.atomic-eggs.com/wae/wae_10.shtml#a5) | Achtung [Agentur](http://www.atomic-eggs.com/cwi/cwi_5.shtml#a5)! | Nichts ist unmöglich? [Doch!](http://www.atomic-eggs.com/cwi/cwi_4.shtml) | [Heute](http://www.atomic-eggs.com/cgi-bin/date_today.pl) schon ge[gök](http://goek.atomic-eggs.com/goek_goek.html)t?
          
          1. » Ich würd' das in etwa so umsetzen:

            » if(callback) callback();

            
            >   
            > Diese Zeile verursacht in der Tat einen stack overflow (so der IE) oder »too much recursion«, so Firefox.  
              
            Nur wenn du die nachfolgende Zeile gelöscht hast, so wie ich es gepostet habe funktioniert es.  
              
            Struppi.
            
            1. Hallo Struppi!

              Nur wenn du die nachfolgende Zeile gelöscht hast, so wie ich es gepostet habe funktioniert es.

              Ich nix gelöscht, 'sch wör!

              Der Stack Overflow bzw. zu tiefe Rekursion kommt auch erst dann, wenn man eben hektisch hovert.

              Viele Grüße aus Frankfurt/Main,
              Patrick

              --
              _ - jenseits vom delirium - _

                 Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
              J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
              1. Der Stack Overflow bzw. zu tiefe Rekursion kommt auch erst dann, wenn man eben hektisch hovert.

                OK, du hast recht, ich nicht genug getestet - ich hab aber schon eine Idee, muss aber erstmal Essen :-)

                Struppi.

              2. Der Stack Overflow bzw. zu tiefe Rekursion kommt auch erst dann, wenn man eben hektisch hovert.

                Probier das mal, ich hoffe ich hab's genug getestet

                var fade = new function() {  
                	var node;  
                	var opacity = 0;  
                	var is_fade_in = true;  
                	var do_next;  
                	var aktiv = false;  
                  
                	function fade_func() {  
                		node.style.filter = 'Alpha(opacity=' + opacity + ')';  
                		node.style.opacity = opacity / 100;  
                		opacity += is_fade_in ? 1 : -1;  
                		window.status = opacity + '/'+ is_fade_in + '/' + do_next + '/' + aktiv;  
                  
                		if((is_fade_in && opacity > 100) || (!is_fade_in && opacity < 0)){  
                			if(do_next) {  
                				if(is_fade_in && do_next < 0 ||  
                				!is_fade_in && do_next > 0) {  
                					is_fade_in = !is_fade_in;  
                					do_next = 0;  
                					window.setTimeout(fade_func, 1000);  
                				}  
                			} else {  
                				aktiv = false;  
                			}  
                			  
                		} else {  
                			aktiv = true;  
                			window.setTimeout(fade_func, 10);  
                		}  
                	};  
                	  
                	this.init = function(action, fade_node) {  
                		action  =  document.getElementById(action);  
                		node =  document.getElementById(fade_node);  
                		if(!action || !node) return;  
                		  
                		action.onmouseover = function() {  
                			if(!aktiv) {  
                				is_fade_in = true;  
                				fade_func();  
                			} else {  
                				do_next = is_fade_in ? 0 : 1; // fade_in  
                			}  
                		};  
                		action.onmouseout = function() {  
                			if(!aktiv) {  
                				is_fade_in = false;  
                				fade_func();  
                			} else {  
                				do_next = !is_fade_in ? 0 : -1; // fade_out  
                			}  
                		};  
                	};  
                };  
                fade.init('foo', 'fadein');  
                
                

                Struppi.

                1. Hallo Struppi!

                  Probier das mal, ich hoffe ich hab's genug getestet

                  [code...]

                  Super, danke.

                  Sorry (auch an die anderen Antworter), wenn ich immer mit Verspätung antworte, es mangelt im Moment etwas an Zeit (sieht man glaube ich am Postingsaufkommen im Vergleich zu früher).

                  Derzeit versuche ich mich durch die schier unendliche DIV-Suppe eines Templates von templatemonster.com durchzukämpfen. Die Designer dort sind anscheinend Graphiker, die es zwar schaffen, valides HTML zu schreiben, aber uhh... zuviel Photoshop im Kopf und gar keine Semantik in den Schuhen!

                  Viele Grüße aus Frankfurt/Main,
                  Patrick

                  --
                  _ - jenseits vom delirium - _

                     Diblom   [link:hatehtehpehdoppelpunktslashslashwehwehwehpunktatomicminuseggspunktcomslash]
                  J'ai 10 ans! | Achtung Agentur! | Nichts ist unmöglich? Doch! | Heute schon gegökt?
      3. Lieber Patrick,

        ich schätze einmal, dass Du die Einblend- oder Ausblend-Funktion einem einzigen Timeout exklusiv erlauben musst, damit sich verschiedene Timeouts nicht in die Quere kommen. Um nun dieses Vorhaben sinnvoll umzusetzen, stelle ich mir folgendes Szenario vor:

        Eine setIntervall-Referenz "tickt" gemütlich vor sich hin. Die damit aufgerufene Funktion testet zwei Parameter. Ein Parameter, nennen wir ihn "anforderung", definiert, ob ein Einblend- oder Ausblend-Vorgang durchzuführen sei. Wenn dem so ist, dann wird dieser Parameter wieder geleert und eine solche Aktion gestartet. Die Fade-Funktion wird dann unterbrechungssicher abgearbeitet.

        Sollte während eines Fadings wieder dieser erste Parameter mit einem gültigen Wert belegt werden, dann kann dieser ja verworfen werden, wenn der gerade laufende Fading-Vorgang dieser "Anforderung" entspricht. Sollte aber ein gegenteiliges Fading angefordert werden, so kann diese Anforderung in den zweiten Parameter, nennen wir ihn "Warteschleife", gesichert werden, bis das aktuell laufende Fading zu Ende ist.

        Wenn ein Fading zu Ende ist, kann der zweite Parameter ("Warteschleife") geprüft werden. Ist er befüllt, wird ein neues Fading gemäß seiner gespeicherten "Anforderung" gestartet.

        Was meinst Du dazu?

        Liebe Grüße,

        Felix Riesterer.

        --
        ie:% br:> fl:| va:) ls:[ fo:) rl:° n4:? de:> ss:| ch:? js:) mo:} zu:)
  4. Moin.

    Eine Idee, wo ich ansetzen soll?

    Verwende einen einzigen Timer per setInterval():

      
    onload = function() {  
        var timer = false,  
            foo = document.getElementById('foo'),  
            pic = document.getElementById('fadein'),  
            opacity = 0;  
      
        function setOpacity(elm, value) {  
            elm.style.opacity = value / 100;  
            elm.style.filter = 'Alpha(opacity=' + value + ')'  
        }  
      
        function clear() {  
            if(timer !== false) {  
                clearInterval(timer);  
                timer = false;  
            }  
        }  
      
        function fadeIn() {  
            if(opacity < 100)  
                setOpacity(pic, ++opacity);  
            else clear();  
        }  
      
        function fadeOut() {  
            if(opacity > 0)  
                setOpacity(pic, --opacity);  
            else clear();  
        }  
      
        foo.onmouseover = function() {  
            clear();  
            timer = setInterval(fadeIn, 9);  
        };  
      
        foo.onmouseout = function() {  
            clear();  
            timer = setInterval(fadeOut, 5);  
        };  
      
        // brauchen wir, da style="opacity: 1;"  
        setOpacity(pic, 0);  
    };  
    
    

    Christoph