JavaScript Codeschnipsel: Farbwechsel im Sonnenlauf

Ich mag es, wenn auf der Webseite dynamische Elemente basierend auf kalendarischen Ereignissen verankert sind, also zum Beispiel der das Hintergrundbild automatisch an die Jahreszeiten angepasst werden. Da ich ein fauler Mensch bin, programmiere ich lieber einen Algorithmus, anstatt von Hand bei jeder Gelegenheit Bilder oder CSS Code auszutauschen.

Aktuell lasse ich die Farbe des Hintergrunds auf meiner Webseite durch das Jahr hinweg anders erscheinen, dabei soll es so sein, dass zum Zeitpunkt der Wintersonnenwende, also rund um den 21./22. Dezember der Hintergrund passend dunkel, hier: schwarz sein soll, wohingegen im Sommer, zur Sommersonnenwende dann natürlich ein helles weiß erstrahlen soll. Der Hintergrund der Webseite passt sich also in den Grautönen der vermeintlichen Helligkeit oder Sonnenstunden am jeweiligen Tag an.

Gelöst habe ich dies mittels einer kleinen JavaScript Funktion, die den CSS Code verändert, die ich hier auch gerne zur Verfügung stelle.

Die Theorie

Die Erde eiert leider gewaltig und somit ist ein Jahr bekanntlich nicht immer gleich lang. Das sogenannte Sonnenjahr beträgt im Mittel rund 365,2422 Tage, weswegen ja auch die Schaltjahre eingeführt wurden, die den Vierteltag wieder kompensieren.

Daneben wird in jedem Jahrtausend das Sonnenjahr sogar noch einmal etwa eine Sekunde länger, doch für meine Zwecke – zumindest gehe ich derzeit davon aus, dass ich den Code nicht über 1000 Jahre nutzen werde – reicht der aktuelle Wert.

Ebenso lasse ich zwei weitere Punkte außer acht: zum Einen, dass die Länge des Sonnenjahres auch zwischen den einzelnen Jahren schwankt und zum Anderen, dass die Helligkeit über das Jahr verteilt nicht unbedingt linear erfolgt..

Die Hintergrundfarbe soll in Grautönen dargestellt werden und von weiß bis schwarz reichen. Grautöne erzielt man relativ einfach im CSS Code, indem alle drei Farbanteile (rot, grün und blau) den gleichen Wert erhalten, also beispielsweise mit dem Code #828282. Die Zeichen nach der ‘#’ werden dabei in Zweiergruppen betrachtet und repräsentieren auf diese Weise und in der Reihenfolge den Farbwert für rot, grün und blau, also jeweils ‘82’. Zu beachten ist dabei allerdings, dass die Werte in Hexadezimalzahlen angegeben werden. Die ‘82’ hier steht somit eigentlich für die Dezimalzahl 130. Auch muss man wissen, dass die Zahlenwerte von 0 (ganz dunkel, bzw. kein Farbanteil) bis 255 (bzw. als Hexadezimalzahl: ‘ff’, ganz hell, bzw. viel Farbanteil) reichen.

Natürlich könnte man auch den gesamten Farbraum mit 16.777.216 verschiedenen Farbtönen abbilden, allerdings wollte ich den Besuchern auf meiner Webseite dabei entstehende grelle Neonfarben ersparen.

Zuletzt möchte ich noch, dass zur Wintersonnenwende das Schwarz, also der Farbwert 0 gegeben ist. Sowohl am Tag davor als auch danach sollte es ebenfalls dunkel sein, erst zur Sommersonnenwende, also ca. ein halbes Sonnenjahr später greift der Farbwert 255. Zu keiner Zeit soll ein “Sprung” von 0 auf 255 oder umgekehrt erfolgen, der Farbverlauf ist sanft und wie ein Pendel: von schwarz langsam zu weiß und dann wieder langsam zurück zum schwarz.

Übrigens: Insgesamt existieren also 256 Farbwerte. Bis auf 0 und 255 wird jeder Farbwert im Jahr zwei mal genutzt, was 510 Änderungen entspricht. Oder umgekehrt: bei 365 Tagen im Jahr ändert sich der Farbwert etwa alle 17 Stunden. Die einzelnen Nuancen sind allerdings so gering, dass es kaum jemanden von heute auf morgen auffallen wird.

Beitrag vorlesen lassen

11 Kommentare

  1. Hallo Michael L. Jaegers,

    Ich möchte gerne dein code Farbwechsel über den Tag
    für ein noch nicht vorhanden Gezeiten Widget auf meiner Website einsetzen allerdings weis ich nicht genau wie ich Ihm implementieren soll.

    Muss ich den kompletten Code in Html einbinden oder kann ich das über ein externer Javascript Datei machen und wie rufe ich den Code dann in Html auf. Kannst du mir ein Code-Kombi beispiel von Javascript und HTML vorgeben??

    vielen lieben Dank!

    Martijn Walk

    1. Hallo Martijn,

      der JavaScript Code kann innerhalb der <script></script> Tags im HTML Code eingebettet werden, oder als separate Datei abgelegt und dann im HTML Code mit <script src=dateinama.js></script> eingebunden werden, wobei “dateiname.js” durch den Namen der Datei ersetzt werden muss, die den JavaScript Code beinhaltet. Ich empfehle die letztere Variante, besonders dann, wenn die Funktion auf mehreren Seiten eingebunden werden soll.

      Anschließend kann die Funktion dann auf der Seite mit z. B. <script>jn_bgcolorBySunYear(73, 2, 8);</script> im HTML Code aufgerufen werden.

      Schönen Gruß,
      Michael

  2. Hallo Herr Jaegers,

    irgendwie klappt es nicht mit dem einbinden.
    ich habe das Script extern eingebunden und rufe das Script wie gesagt im Html auf.
    der Body habe ich im CSS mit eine Farbe #ffffff angegeben.

    Eine andere Frage wäre, kann ich das Script auch klassifizieren um die Hintergrundfarbe einen Container den Farbwechsel zu verpassen. Das würde den Zweck für meine Vorstellung erfüllen.

    1. Hallo Herr Walk,

      die Angaben reichen nun nicht für eine geeignete Ferndiagnose, da müsste ich schon eine URL haben, auf der das Script eingebunden sein sollte.

      Mit minimalen JavaScript Kenntnissen kann das Script auch dergestalt angepasst werden, dass andere HTML Elemente, z. B. die Hintergrundfarbe eines Containers, verändert wird.

      So findet sich die entscheidende Stelle im Code an zwei mal mit

      document.body.style.backgroundColor = ...

      Mit

      document.getElementById('id').style.backgroundColor = ...

      und id als Id Attribut des gewünschten Objekts, sollte es dann auch funktionieren.

      Schönen Gruß,

      Michael Jaegers

      1. Hallo Herr Jaegers,

        ich habe das unfertige Widget auf meine Website unter Sitemap> test eingebunden aber das aufrufscript im Html heraus genommen da ich selber noch herum probiere. Ich möchte lediglich das der hellblaue Hintergrund in dunkelblau nach verlauf des Tages verändert, dafür müsste class “colorchange” angesprochen werden.

        Ich hoffe ich mache Ihnen nicht zuviel mühe und wäre sehr dankbar wenn Sie mir einige Instruktionen geben könnten.

        besten Dank Martijn Walk

  3. ah erleuchtung das Script tut was, nach dem ich den Code für ID eingegeben habe und das Ausführscript mit true und eine Farbe im Javascript eingefügt habe. Jetzt schauen welche Werte ich im Javascript sonnst noch ändern muss um von hellblau nach dunkelblau und zuruck zu gehen.

    Vielleicht können Sie mir an der Stelle weiter helfen..

    Liebe grüße,

    Martijn Walk

    1. Hallo Herr Walk,

      um eine andere Farbe für den Farbverlauf zu wählen, sollte es reichen den RGB Farbcode beim Aufruf der Funktion mit anzugeben. Also etwa wie folgt:

      jn_bgcolorByDayTime(false, 0, 51, 102)

      wobei 0, 51 und 102 die Dezimalwerte für rot, grün und blau sind. Das false als erster Parameter sorgt dafür, dass sich die Farbe nicht alle zweieinhalb Minuten automatisch verändert, wie oben beschrieben. Es muss also an der eigentlichen Funktion nichts verändert werden.

      Schönen Gruß,

      Michael Jaegers

  4. Moin Herr Jaeger,

    es klappt!! falls ich das grau was um 00:00 komplett ist in ein Dunkelblau haben möchte welchen Parametern muss ich dann ändern? der Farbe im Css ID wird komplett überschrieben vom Javascript und hat inprinzip keine Funktion mehr bzw. lediglich als Fallback-Farbe.

    ist es dann notwendig alle 255 Werte auf z.B. 40,57,79 zu ändern und oder /auch der letzte Parameter der im Originalscript mit den Wert: 169412 (ein sattes grün wie ich gesehen habe), ändern.

    also nachts den Wert 40,57,79 und tagsüber den Wert 139,202,243

    Ich freue mich auf ein letzten Antwort und bedanke mich herzlichst.

    1. Hallo Herr Walk,

      das Skript rolliert – so wie es aktuell programmiert ist – über eine (!) Farbe, verändert dann aber die Farbsättigung von 0 bis 100% und zurück.

      Möchte man, wie ich Ihrem Kommentar entnehme, über zwei unterschiedliche Farben (40, 57, 79, bzw. 139, 202, 243) rollieren, ist eine andere Berechnung erforderlich, bzw. muss die Berechnung über alle Farbwerte (plus ggf. die Sättigung) erfolgen. Siehe hierzu auch den Wikipediabeitrag zum Farbgradienten (https://de.wikipedia.org/wiki/Farbgradient).

      Der lineare (und ggf. nicht ganz optimale Ansatz) lässt sich wohl hiermit abbilden:

      &lt;code&gt;function gradient(color1, color2, weight) {
      var w1 = weight;
      var w2 = 1 – w1;
      return [
      Math.round(color1[0] * w1 + color2[0] * w2),
      Math.round(color1[1] * w1 + color2[1] * w2),
      Math.round(color1[2] * w1 + color2[2] * w2)
      ];
      }&lt;/code&gt;

      color1 und color2 sind jeweils Felder mit den drei Farbwerten für Start und Ende.
      weight beinhaltet den Faktor für den Fortschritt im Tag, also Mitternacht 0, Mittag 1; dazwischen jeweils anteilig abgestuft.
      Als Ergebnis liefert die Funktion dann wiederum ein Feld mit den drei Werten für R, G und B.

      Für den Nicht-linearen Verlauf berechnen sich dann die einzelnen Werte in der Funktion mit

      &lt;code&gt;Math.round(Math.sqrt(Math.pow(color1[i], 2) * w1 + Math.pow(color2[i], 2) * w2))&lt;/code&gt;

      mit i=0 bis 2.

      Ohne dies nun getestet zu haben, sollte der Code dann insgesamt wie folgt aussehen:

      &lt;code&gt;function jn_bgcolorByDayTime(loop, r1, g1, b1, r2, g2, b2) {
      var r1 = typeof r1 !== ‘undefined’ ? r1 : false;
      var g1 = typeof g1 !== ‘undefined’ ? g1 : false;
      var b1 = typeof b1 !== ‘undefined’ ? b1 : false;

      var r2 = typeof r2 !== ‘undefined’ ? r2 : false;
      var g2 = typeof g2 !== ‘undefined’ ? g2 : false;
      var b2 = typeof b2 !== ‘undefined’ ? b2 : false;

      // Länge eines Tages in Millisekunden
      var dayTime = 86400000; // = 24*60*60*1000

      // aktuelles Datum ermitteln
      var date = new Date();

      // Berechnung des Fortschritts am Tag, wobei ein Kreis beschrieben wird,
      // also von 0 über 1 zurück zur 0
      var progress = 255 – Math.round(255 * Math.abs(2*(1000 * (date.getSeconds() + 60 * (date.getMinutes() + 60 * date.getHours())) + date.getMilliseconds() – dayTime/2))/dayTime);

      // CSS Code austauschen
      if (r1 === false || g1 === false || b1 === false) {
      // bei fehlender oder unvollständiger Farbvorgabe
      // Umwandeln des Werts in eine Hexadezimalzahl
      var hexCode = progress.toString(16);
      if (hexCode.length &lt; 2) hexCode = ‘0’ + hexCode;
      document.body.style.backgroundColor = ‘#’ + hexCode + hexCode + hexCode;
      } else if (r2 === false || g2 === false || b2 === false) {
      // mit Startfarbvorgabe, rollieren über Sättigung
      document.body.style.backgroundColor = ‘rgba(‘ + r1 + ‘,’ + g1 + ‘,’ + b1 + ‘,’ + progress / 255 + ‘)’;
      } else {
      // mit Start- und Zielfarbvorgabe, rollieren über den Gradienten zwischen den beiden Farben
      document.body.style.backgroundColor = ‘rgba(‘
      + Math.round(Math.sqrt(Math.pow(r1, 2) * w1 + Math.pow(r2, 2) * w2)) + ‘,’
      + Math.round(Math.sqrt(Math.pow(g1, 2) * w1 + Math.pow(g2, 2) * w2)) + ‘,’
      + Math.round(Math.sqrt(Math.pow(b1, 2) * w1 + Math.pow(b2, 2) * w2)) + ‘,255)’;
      }

      if (typeof loop !== ‘undefined’ &amp;&amp; loop)
      window.setTimeout(‘jn_bgcolorByDayTime(true,’ + r1 + ‘,’ + g1 + ‘,’ + b1 + ‘,’ + r2 + ‘,’ + g2 + ‘,’ + b2 + ‘)’, 169412);
      }&lt;/code&gt;

      Der Funktionsaufruf lautet dann jn_bgcolorByDayTime(loop, r1, g1, b1, r2, g2, b2), wobei r1, g1 und b1 die Werte für die erste und r2, g2 und b2 die Farbwerte für die zweite Farbe darstellen.

      Schönen Gruß,
      Michael Jaegers

Kommentar hinterlassen

Nutze dieses Kommentarfeld um deine Meinung oder Ergänzung zu diesem Beitrag kundzutun. Verhalte dich bitte respektvoll und höflich! Kommentare werden vor der Veröffentlichung in der Regel moderiert und bei Verstößen gegen geltendes Recht, die guten Sitten, fehlendem Bezug oder missbräuchlicher Verwendung nicht freigegeben oder gelöscht.
Über die Angabe deines Namens, deiner E-Mail Adresse und deiner Webseite freuen wir uns, doch diese Felder sind optional. Deine E-Mail Adresse wird dabei zu keinem Zeitpunkt veröffentlicht.

Um mit dem Betreiber dieser Seite nicht-öffentlich in Kontakt zu treten, nutze die Möglichkeiten im Impressum.