Thomas Brenner: Geschwindigkeitsprobleme bei Javascript-animiertem Farbtext

Tag zusammen,

ich bin gerade dabei mich ein Bisschen in Html und Javsascript einzuarbeiten, und schrieb zur Übung beiligendes Programm. Es ermöglicht die Darstellung animierter Farbtexte mittels style-Attributen (siehe Beschreibung im Programmtext). Obwohl der Rechenaufwand meiner Meinung nach relativ gering sein sollte, führt selbst das beiligende Beispiel mit relativ wenig animiertem Farbtext zu einer hohen Systemauslastung (AMD Sempron 2300+ bei 50%). Aus Neugier und auch in Hinblick auf eine eventuelle spätere Anwendung würde ich nun gerne wissen, ob sich da irgendetwas machen läßt (ich könnte mir zum Beispiel vorstellen, das der Browser nach jeder erfolgten Farbänderung (die ja Buchstabe für Buchstabe für den ganzen Text und das ca. 20mal pro Sekunde vorgenommen wird; bei beispielsweise 184 Buchstaben (beiligendes Beispiel) also 3680 mal/s) das ganze Fenster aktualisiert, was aber eigentlich nicht nötig wäre (reicht nach erfolgter Farbänderung des gesamten Textes, also 20 mal/s) oder etwas derartiges), oder ob evt. Javascript an sich sehr langsam und für etwas rechenintensievere Anwendungen nicht gedacht ist.

P.S.: bisher nur mit IE 6.0 getestet

-----Programmcode------ (tschuldigung, geht leider nicht anders (habe keine eigene Homepage) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">

<html> <head> <title>javascript-animierter Farbtext</title>

<script type="text/javascript"> <!--//ThBr0205

akz=25; //Aktualisierungszeit in ms; entsprechend der minimal zu erwartender Prozessorgeschwindigkeit und    //animierter Textmenge anpassen; optimal 25ms;

//Standardwerte; gesetzt, wenn nichts anderes angegeben ga = -180;  //Geschwindigkeit; Grad/Sekunde (ca.); Laufrichtung: pos.<-; neg.-> 0:stehend aa = 127;   //Amplitude; max. 255/2 ca = 10;    //Periode; Grad/Buchstabe; 0->gesamter Text hat gleiche Farbe va = 127;   //Verschiebung vertikal 0<=va-aa<va+aa<=255

//Im Folgenden werden verschiedene Listen definiert, die Verwendung finden, wenn die Attribute für die 3 Grundfarben //einzeln gesetzt werden sollen (Auswahl mit Style(<attr>d<Listennummer>; Reihenfolge:RGB; nach Belieben editierbar //---Farbzusammensetzungen--- fa = new Array(); fa[0] = new Array(0,120,240); fa[1] = new Array(0,30,60); fa[2] = new Array(0,170,190); fa[3] = new Array(0,0,0);

//---Geschwindigkeiten--- ge = new Array(); ge[0] = new Array(-180,90,360); ge[1] = new Array(30,200,400); ge[2] = new Array(-180,-180,-180); ge[3] = new Array(180,180,180);

//---Amplitude--- ae = new Array(5); ae[0] = new Array(127,0,0); ae[1] = new Array(127,63,31); ae[2] = new Array(0,127,0); ae[3] = new Array(0,0,127); ae[4] = new Array(90,90,0); ae[5] = new Array(107,70,70);

//---Frequenz--- ce = new Array(); ce[0] = new Array(40,20,10); ce[1] = new Array(20,3,12);

//---Verschiebung--- ve = new Array(); ve[0] = new Array(127,0,0); ve[1] = new Array(127,63,31); ve[2] = new Array(0,127,0); ve[3] = new Array(0,0,127); ve[4] = new Array(165,165,0); ve[5] = new Array(147,110,110);

//Beispiel: <span style="tfvm:1; tfvp:0; tfvg:d0; tfvc:20; tfva:d1;">text</span> //     tfvm:1  -> Text mit Farbverlauf aktivieren //     tfvp:0  -> Palette 0 (siehe oben -> Regenbogen) //     tfvg:d0 -> Geschwindigkeiten für 3 Grundfarben werden einzeln //          gesetzt (entsprechend Definitionsliste ve[0]) //     tfvc:20 -> Periode für 3 Grundfarben = 20 //     tfva:d1 -> Amplituden werden einzeln gesetzt (Defitionsliste ae[1]) //     tfvv ist nicht definiert -> Standardwert wird gesetzt (va) //  Es muß ein neuer Span-Bereich mit den entsprechenden Style-Informationen definiert werden, //  befinden sich diese im Style-Bereich eines übergeordneten Elements, werden sie nicht ausgewertet! //  Der so definierte Span-Bereich kann keine weiteren Kind-Elemente außer dem Text selber enthalen!

//mit //ul gekennzeichnete Zeilen können entfernt werden, dienen lediglich der Visualisierung der Farbanteile //der einzelnen Buchstaben des ausgewählten Textes (rechtes Fenster)

fvzm=1; fvzi=2; //ul

hk = new Array("0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f");

function dinit(){       anys=document.getElementById("anid").style.top;  //ul    anxs=document.getElementById("anid").style.left; //ul    anxw=0; anyw=0; des=1; //ul    for (co1=anxs.length-3;co1>=0;co1--){ //ul    anxw+=anxs.slice(co1,co1+1)des; //ul    anyw+=anys.slice(co1,co1+1)des; //ul    des=10; //ul    } //ul    anxw+=9; //ul    anyw+=132; //ul    ga=gaakz/1000;    for (co1=0;co1<ge.length;co1++) for (co2=0;co2<3;co2++) ge[co1][co2]=ge[co1][co2]akz/1000;    anz=0;    spa=document.getElementsByTagName("span").length;    bta=0;    btsi = new Array();    bti = new Array();    btp = new Array();    btan = new Array("tfvg","tfvc","tfva","tfvv");     bl=btan.length;    btaw = new Array();    btamu = new Array();       for (co4=0;co4<spa;co4++){   be=document.getElementsByTagName("span")[co4];   if (be.style.tfvm=="1"){     btsi[bta]=co4;     bf=be.firstChild;     bti[bta]=bf.nodeValue;     pai=(be.style.tfvp==undefined)?0:be.style.tfvp;     btp[bta] = new Array(3);     for (co1=0;co1<3;co1++) btp[bta][co1]=fa[pai][co1];     btaw[bta] = new Array(bl);     btamu[bta] = new Array(bl);     for (co1=0;co1<bl;co1++){    switch(co1){      case 0:{aat=be.style.tfvg; ave=ga; kf=akz/1000; break;}      case 1:{aat=be.style.tfvc; ave=ca; kf=1; break;}      case 2:{aat=be.style.tfva; ave=aa; kf=1; break;}      case 3:{aat=be.style.tfvv; ave=va; kf=1; break;}    }    if (aat==undefined) {      btaw[bta][co1]=ave;      btamu[bta][co1]=1;    }    else  if (aat.slice(0,1)=="d"){      btaw[bta][co1]=aat.slice(1,aat.length);      btamu[bta][co1]=0;      }      else {     btamu[bta][co1]=1;     btaw[bta][co1]=aatkf;      }     }     be.removeChild(bf);     btam=bta;     vvt_v(1);        spa=document.getElementsByTagName("span").length;     bta++;   }    }    an_v(); //ul + entsprechende Funktion    an_t(fvzi); //ul    vttf(); }

function vvt_v(ini){    ba=document.getElementsByTagName("span")[btsi[btam]];    fm = Array(3);    for (co1=0;co1<3;co1++) fm[co1]=btp[btam][co1];    if (fvzm==1 && btam==fvzi && ini==1) an_ini(); //ul    for (co1=0;co1<bti[btam].length;co1++){      if (ini==1){        mz=bti[btam].slice(co1,co1+1);     if (mz==' ') mz=' ';     ba.appendChild(document.createElement("span"));     bb=ba.lastChild;        bb.appendChild(document.createTextNode(mz));   }   else if (co1==0) bb=ba.firstChild;     else bb=bb.nextSibling;   ds="#"; vs="ff0000";   for (co2=0;co2<3;co2++){      sf=(btamu[btam][2]==1)?btaw[btam][2]:ae[btaw[btam][2]][co2];      fve=(btamu[btam][3]==1)?btaw[btam][3]:ve[btaw[btam][3]][co2];     fwm=Math.round(Math.sin(fm[co2]/180Math.PI)sf+fve);     uhc=Math.round(fwm/16-0.5);        lhc=fwm-uhc16;     ds+=hk[uhc]+hk[lhc];      if (btam==fvzi && fvzm==1){ //ul    if (co1==0 && co2==0) na=document.getElementById("susi"); //ul       else na=na.nextSibling; //ul            na.style.top=anyw-fwm/2+"px"; //ul       na.style.left=co1df+anxw+"px"; //ul     } //ul   }   bb.style.color=ds;   for (co2=0;co2<3;co2++){     pp=(btamu[btam][1]==1)?btaw[btam][1]:ce[btaw[btam][1]][co2];     fm[co2]+=pp;     if (fm[co2]>360) fm[co2]-=360;   }    } }

function an_ini(){ //ul     for (co1=0;co1<bti[fvzi].length;co1++){    vs="ff0000";    for (co2=0;co2<3;co2++){   fwm=Math.round(Math.sin(fm[co2]/180*Math.PI)sf+127);      na=document.getElementsByTagName("body")[0];      na.appendChild(document.createElement("span"));      na=na.lastChild;      if (co1==0 || co2==0) na.id="susi";      na.style.position="absolute";   na.style.top=anyw;   na.style.left=anxw;      na.style.color="#"+vs;      vs=vs.slice(0,4);      vs="00"+vs;      na.appendChild(document.createTextNode(""));      df=200/(bti[fvzi].length-1);    }     }   }

function vttf(){     for (co2=0;co2<bta;co2++){ for (co3=0;co3<3; co3++){    if (btamu[co2][0]==1) btp[co2][co3]+=btaw[co2][0];    else btp[co2][co3]+=ge[btaw[co2][0]][co3];    if (btp[co2][co3]>360) btp[co2][co3]-=360;    if (btp[co2][co3]<0) btp[co2][co3]+=360; } } for (btam=0;btam<bta;btam++) vvt_v(0);     anz++;     document.getElementById("aau").firstChild.nodeValue=anz;     window.setTimeout("vttf()",akz);   }

function an_v(){ //ul     var bt; if (fvzm==1){    fvzm=0;    bt="Animation ein"; } else {    fvzm=1;    bt="Animation aus"; } document.getElementById("aab").value=bt;   }

function an_dini(){ //ul nb=document.getElementsByTagName("body")[0]; for (co1=0;co1<bti[fvzi].length*3;co1++) nb.removeChild(nb.lastChild);   }

function an_t(ti){ //ul     document.getElementById("az").firstChild.nodeValue=bti[ti];   }

function an_v2(ei){ //ul     if (fvzm==1){    an_dini();    fvzi=ei;    an_ini();    an_t(fvzi); }   } //--> </script> </head>

<body id="bod" style="background-color:#ebf498;" onLoad="dinit()"> <div style="font-size:40px;">Am Ende des <span id="pam" style="tfvm:1; tfvp:0; tfvg:-400; tfvc:20;" onClick="an_v2(0)">Regenbogens</span> soll man, so wird es überliefert, <span style="tfvm:1; tfvp:3; tfva:d4; tfvv:d4; tfvc: 30; tfvg:-100;" onClick="an_v2(1)">einen Pott Gold</span> finden können. <br /><br /><br /> <p>Uschi hat sich gestern <span style="tfvm:1; tfvg:d0" onClick="an_v2(2)">einen neuen Farbfernseher</span> gekauft <br /> <span onClick="an_v2(3)" style="tfvm:1; tfvp:0; tfva:d1; tfvv:d1; tfvg:400; font-size:30px; position:absolute; left:300px;">die Farben ihres Alten waren schon etwas bläßlich</span></p></div> <span style="font-size:30px; position:absolute; left:300px;">und Omas Alter schwarz-weiß Fernseher</span> <span onClick="an_v2(4)" style="tfvm:1; tfvp:3; tfva:d5; tfvv:d5; tfvg:400; tfvc:15; font-size:30px; position:absolute; left:795px;">hat einen Rotstich (?)</span></p></div><br /> <br /><br /><br /> <span onClick="an_v2(5)" style="font-size:40px; tfvm:1; tfvp:1; tfvg:d2; tfvc:d0;">VORWÄRTS</span>&#160;&#160;&#160;immer,&#160;&#160;&#160;<span onClick="an_v2(6)" style="font-size:40px; tfvm:1; tfvp:1; tfvg:d3; tfvc:d0;">RÜCKWÄRTS</span>&#160;&#160;&#160;nimmer, nur wie, da hab ich keinen&#160;&#160;&#160;<span onClick="an_v2(7)" style="font-size:40px; tfvm:1; tfvp:1; tfvg:180; tfvc:0;">SCHIMMER</span> <br /><br /> <!-- <span onClick="an_v2(5)" style="tfvm:1; tfvp:0; tfvc:d0; font-size:50px; border-bottom-style:solid">kleine Farbenlehre</span> <br /><br /><br /> <table border="1" cellpadding="1" style="font-size:30px"> <colgroup width="150px"; span="3"></colgroup> <tr>        <th>Farbe</th>        <th>Dezimal</th>        <th>Hexcode</th> </tr> <tr>        <td><span onClick="an_v2(8)" style="tfvm:1; tfvp:0; tfva:d0; tfvv:d0;">rot</span></td>        <td>255-0-0</td>        <td>ff0000</td> </tr> <tr>        <td><span onClick="an_v2(9)" style="tfvm:1; tfva:d2; tfvv:d2;">gruen</span></td>        <td>0-255-0</td>        <td>00ff00</td> </tr> <tr>        <td><span onClick="an_v2(10)" style="tfvm:1; tfva:d3; tfvv:d3;">blau</span></td>        <td>0-0-255</td>        <td>0000ff</td> </tr> </table><--> <div Id="anid" style="position:absolute; top:550px; left:900px; width:227px; height:151px; border-style:solid; border-width:3px;"> <h3 style="position:absolute; top:-70px; left:0px;">Farbverlauf von</h1> <span id="az" style="position:absolute; top:-45px; left:20px; font-size:15px; color:#687bf8;">a</span> <form style="position:absolute; top:155px; left:0px;"> <input id="aab" type="button" value="Animation ein" onClick="an_v()"> </form> <span id="aau" style="position:absolute; top:155px; left:190px; font-size:15px;">a</span> <span style="position:absolute; top:200px; left:0px; font-size:15px;">Animation des Farbverlaufs durch Klicken auf den entsprechenden Text</span> </div> </body> </html>

  1. hi,

    Obwohl der Rechenaufwand meiner Meinung nach relativ gering sein sollte, führt selbst das beiligende Beispiel mit relativ wenig animiertem Farbtext zu einer hohen Systemauslastung (AMD Sempron 2300+ bei 50%).

    der reine javascriptseitige rechenaufwand dürfte in der tat so gering sein, dass er kaum ins gewicht fällt.

    ich könnte mir zum Beispiel vorstellen, das der Browser nach jeder erfolgten Farbänderung (die ja Buchstabe für Buchstabe für den ganzen Text und das ca. 20mal pro Sekunde vorgenommen wird; bei beispielsweise 184 Buchstaben (beiligendes Beispiel) also 3680 mal/s) das ganze Fenster aktualisiert, was aber eigentlich nicht nötig wäre (reicht nach erfolgter Farbänderung des gesamten Textes, also 20 mal/s) oder etwas derartiges

    so in etwa ist es.
    der browser muss die seite, oder teile von ihr, neu "rendern", die darstellung neu aufbauen. und je nachdem, wie er das macht, dauerts halt schon mal länger.

    da bleiben dir m.E. kaum andere möglichkeiten, als die intervalle zu vergrößern - 20 mal pro sekunde ist schon etwas heftig.
    das wäre ja fast schon kinofilm- oder fernsehqualität, mit 25(?) einzelbildern pro sekunde. diese "qualität" muss eine animation m.E. nicht aufweisen - größere intervalle wären angebracht, etwas mehr "ruckeln" stört den betrachter nicht so sehr, als wenn du die performance seines systems in den keller treibst.
    zumal, wenn es "nur" um eine animation der farbwerte geht(?) - wechsel in der farbe eines objektes werden vom besucherauge m.E. nicht so stark/schnell registriert, wie es bei einer bewegung des objektes der fall wäre.

    oder ob evt. Javascript an sich sehr langsam und für etwas rechenintensievere Anwendungen nicht gedacht ist.

    an die grenzen dessen, was javascript bei berechnungen zu leisten vermag, dürftest du hier sicher noch nicht gestoßen sein - wie du ganz richtig vermutest, dürfte die umsetzung der style-änderungen durch die rendering engine der "flaschenhals" sein.

    P.S.: bisher nur mit IE 6.0 getestet

    bin selber gerade an einer kleinen animation am feilen, bei der die relative position mehrerer kleiner objekte dynamisch mehrfach hintereinander zeitgesteuert verändert wird. und da schneidet der IE von der performance her am schlechtesten ab ...

    gruß,
    wahsaga

    --
    "Look, that's why there's rules, understand? So that you _think_ before you break 'em."
    1. Hallo wahsaga,

      bin selber gerade an einer kleinen animation am feilen, bei der die relative position mehrerer kleiner objekte dynamisch mehrfach hintereinander zeitgesteuert verändert wird. und da schneidet der IE von der performance her am schlechtesten ab ...

      echt? Bei meinen Grafikversuchen http://www.j-berkemeier.de/FktPlot.html und besonders bei http://www.j-berkemeier.de/LogistischeAbbildung.html ist der IE deutlich schneller als Mozilla/Firefox. Vieleicht sollten wir unsere Versionen mal vergleichen und etwas basteln, das auf beiden Browsern schnell läuft.

      Gruß, Jürgen

    2. Hallöchen,

      so in etwa ist es.
      der browser muss die seite, oder teile von ihr, neu "rendern", die darstellung neu aufbauen. und je nachdem, wie er das macht, dauerts halt schon mal länger.

      gibt es irgendeine Möglichkeit die ständige Aktualisierung der Seite mit jeder Inhaltsänderung zu unterbinden, und sie dann zu einem bestimmten Zeitpunkt, wenn der Seiteninhalt komplett geändert ist, per Befehl zu erzwingen?

      bin selber gerade an einer kleinen animation am feilen, bei der die relative position mehrerer kleiner objekte dynamisch mehrfach hintereinander zeitgesteuert verändert wird. und da schneidet der IE von der performance her am schlechtesten ab ...

      Da kann ich mich dem Beantworter deiner Nachricht, soweit ich damit Erfahrung habe, nur anschließen. Hab mal einen kleinen Wellentext mit Javascript animiert, und zumindest Opera war dabei wesentlich langsamer als der IE.

      Danke + Tschüssi

      Thomas