Animation mit JS läuft zu langsam

Toffi123

Grünschnabel
Hallo,

ich spiele zur Zeit etwas mit JavaScript herum und versuche mich gerade an einer animierten Navigation. Das ganze ist so geplant, dass sich ein <div>-Container per setTimeout von 0px Breite auf einen bestimmten Wert "ausdehnt". Funktioniert bisher auch alles prima, allerding habe ich nun das Problem, dass die Animation zu langsam abläuft.

Die Funktion, die ich geschrieben habe schaut folgendermaßen aus:
Code:
//id ist die ID des zu ändernden Containers,
//value die Breite, die erreicht werden soll, und
//speed die Geschwindigkeit, bzw. die Verzögerung.

function scaleContainerWidth(id, value, speed) {
    if (parseInt(getProperty(id, "width")) == value) {
        return true;
    } else if (parseInt(getProperty(id, "width")) > value) {
        document.getElementById(id).style.marginLeft=(document.body.offsetWidth - parseInt(getProperty(id, "width"))) / 2 + "px";
        document.getElementById(id).style.width = parseInt(getProperty(id, "width")) - 1 + "px";
        setTimeout("scaleContainerWidth(\""+id+"\", "+value+", "+speed+")", speed);
    } else if (parseInt(getProperty(id, "width")) < value) {
        document.getElementById(id).style.marginLeft=(document.body.offsetWidth - parseInt(getProperty(id, "width"))) / 2 + "px";
        document.getElementById(id).style.width = parseInt(getProperty(id, "width")) + 1+ "px";
        setTimeout("scaleContainerWidth(\""+id+"\", "+value+", "+speed+")", speed);
    }
}

(Die Funktion getProperty die ich verwende gibt den style-Wert des übergebenen Elements und der übergebenen Eigenschaft zurück.)

Doch selbst wenn ich die Funktion jetzt mit 0 als speed aufrufe schleicht das ganze ziemlich.

Zwar könnte man jetzt pro Schritt den div gleich um z.B 5 Pixel vergrößern, das Problem ist nur, dass die Breite nicht fix ist, sondern variieren kann, d.h., dass der gewünschte Wert nie erreicht wird wenn die Breite nicht durch 5 teilbar ist.

Ich habe jetzt schon einige Zeit gesucht aber leider nichts gefunden. Gibt es denn eine elegante Lösung, oder muss ich jedesmal überprüfen, ob die errechnete Breite geteilt durch 5 einen Rest ergibt und evtl. aufgestockt werden muss?
 
Zuletzt bearbeitet:
Ich habe sowas ähnliches nun mit der Sinus Funktion gemacht , das ein Bereich einfach so aufslidet. Es soll schnell losgehen und hinten immer langsamer werden.

es sieht ja quasi so aus dann :

Zuerst brauchen wir den Sinus für einen schnelleren start das es am Ende etwas langsamer wird. Also die Schrittweite mit der die Box wächst gegen Ende hin immer kleiner werden.

Eine Beschleunigung ich habe da 0.11 mal einfach so gewählt läuft schön flüssig und nicht zu schnell. Je höher die Beschleunigung desto schneller wird es.

Einen Startwert / Geschwindigkeit welchen wir als Radianten nehmen.

Dann noch den Haltepunkt das wäre bei PI / 2 wenn der Wert über PI / 2 geht bis hin zu PI würde es in die andere Richtung gehen und bei einen Wert über PI bis 3/2 PI eben wieder vorwärts etc.

sin ( radiant ) gibt uns einen Wert zurück von -1 bis 1 bzw bei einen Radianten von 0 bis PI / 2 einen Wert von 0 bis 1 wobei dieser wert nun stetig wachsen würde. Diesen Wert multipliziert mit der Weite die die Box gesamt erreichen kann würde nun die tatsächliche Weite der Box geben. Am Ende wird die aktuelle Schrittweite immer kleiner werden.

also würde die Formel so aussehen:

var new_x (y) = Math.sin(radiant) * Weite (Höhe);

Nach jedem Duchgang wird der Radiant um die Beschleunigung erhöt bis der wert größer als PI / 2 wird , dann wird die Box auf die volle Weite gesetzt und das Intervall abgebrochen.

HTML:
<html>
    <head>
        <style type="text/css">
            #testcontainer {
                width:900px;
                height:300px;
                background:#3d3d3d;
            }
        </style>
        <script type="text/javascript">
            var velocity = 0.11;
            var speed    = 0;
            var w = 0;
            var h = 0;
            var element = null;

            function slide(grow_x,grow_y){
                var current_width  = 0;
                var current_height = 0;
                
                speed += velocity;            
                            
                if(grow_x) current_width  = w*Math.sin(speed); else current_width  = w;
                if(grow_y) current_height = h*Math.sin(speed); else current_height = h;
                
                if(speed > Math.PI/2) {
                
                    element.style.height = h+"px";
                    element.style.width  = w+"px";
                    
                    return;
                } else {
                
                    element.style.height = parseInt(current_height) + "px";
                    element.style.width  = parseInt(current_width)  + "px";
                
                    window.setTimeout("slide("+grow_x+","+grow_y+")",30);
  
                }
                
            }

            window.onload = function(){
                element  = document.getElementById('testcontainer');

                w = element.offsetWidth;
                h = element.offsetHeight;
                
                element.style.width  = "0px";
                element.style.height = "0px";
                
                slide(true,true);
            };
        </script>
    </head>
    <body>
        <div id="testcontainer"></div>
    </body>
</html>

Hier mal so als Beispiel wie es aussehen könnte am Ende.
 
Zuletzt bearbeitet:
Bitte gern ;) Es empfiehlt sich noch zumal die Geschwindigkeit oder hier speed genannt nach dem vollen vergrößeren wieder auf 0 zu setzen.

Des weiteren muss man aufpassen bei der Berechnung bei pi / 2 < speed < pi bekommen wir Werte zwischen 0 und -1 und somit würdest du negative Höhen und negative Weiten bekommen.

Ein Math.abs(current_height) oder Math.abs(current_width) würde die Zahl immer positiv erscheinen lassen somit gibt es nie negative Höhen und Weiten , gibs zwar auch so nicht aber er würde versuchen es durchzubekommen ;)
 
Zurück