Auf dieser Seite erkläre ich, wie man die Farbtonwerte des hsl() Farbsystems in RGB Werte umwandelt. Wir lernen das Prinzip der Farbmodelle HSL und RGB kennen und programmieren Schritt für Schritt, einen Javascript Konverter von HSL zu RGB.
Damit es zu Anfang nicht zu kompliziert ist, lasse ich die Sättigung auf 100% und Helligkeit auf 50%. Das heißt es geht erstmal nur um die Umrechnung der 360 Farbtonwerte auf dem 360° Farbkreis in RGB also in die Werte Rot, Grün und Blau .
Basics zu RGB und HSB findet ihr in meinem Grundlagen Bildverarbeitung & Farbmodelle Tutorial
Auf den HSL-Reglern kannst du die Farbe in RGB anzeigen lassen. Belasse die Sättigung auf 100% und die Helligkeit auf 50%. Das ergibt eine kräftige satte Farbe.
Verändere den Farbton von einer Seite zur anderen und beobachte, wie die Werte für Rot, Grün und Blau ansteigen, eine Zeit lang stehen bleiben und dann wieder absteigen.
const sector = Math.floor(h / 60);
const fraction = (h / 60)-sector;x = Math.round(255 * fraction); invX = 255 - x; abfallender FarbwertIhr habt die Funktion und könnt mit folgendem Slider die Werte der Variablen beobachten.
function hToRgb(h) {
// 1. Den Winkel auf 0-360 normieren
h = h % 360;
// 2. Wir teilen den Kreis in 6 Teile (je 60 Grad)
// Ein Teil entspricht 255 Einheiten in RGB
const sector = Math.floor(h / 60);
const fraction = (h / 60) - sector;
const x = Math.round(255 * fraction); // Der "Anstieg" oder "Abfall"
const invX = 255 - x;
switch(sector) {
case 0: return `rgb(255, ${x}, 0)`; // Rot voll, Grün steigt
case 1: return `rgb(${invX}, 255, 0)`; // Grün voll, Rot fällt
case 2: return `rgb(0, 255, ${x})`; // Grün voll, Blau steigt
case 3: return `rgb(0, ${invX}, 255)`; // Blau voll, Grün fällt
case 4: return `rgb(${x}, 0, 255)`; // Blau voll, Rot steigt
case 5: return `rgb(255, 0, ${invX})`; // Rot voll, Blau fällt
}
}
Nun folgt der nächste Schritt. Wir behalten die Helligkeit bei 50% und es kommt die Sättigung hinzu. Wenn die Sättigung (S) sinkt, „ziehen“ wir die RGB-Werte zur Mitte hin zusammen.Bei 100 % Sättigung liegt der tiefste Wert bei 0. Wenn wir die Sättigung senken, steigt dieser Boden an. Die Farbe wird „blasser“, weil sich die RGB-Kanäle angleichen. Bedenke, wenn alle 3 RGB Werte gleich sind, erhält man einen Grauton.
function hsToRgb(h, s) {
h = h % 360;
s = s / 100; // Umwandlung in 0 bis 1
// Bei 50% Helligkeit ist dies der maximale Ausschlag nach oben/unten
const range = 255 * s;
const high = 127.5 + (range / 2); // Der höchste Wert (bei 100% S = 255)
const low = 127.5 - (range / 2); // Der tiefste Wert (bei 100% S = 0)
const sector = Math.floor(h / 60);
const fraction = (h / 60) - sector;
// Berechnung der ansteigenden und abfallenden Flanke innerhalb der Range
const rise = Math.round(low + (high - low) * fraction);
const fall = Math.round(high - (high - low) * fraction);
const hi = Math.round(high);
const lo = Math.round(low);
switch(sector) {
case 0: return `rgb(${hi}, ${rise}, ${lo})`; // Rot stabil hoch, Grün steigt
case 1: return `rgb(${fall}, ${hi}, ${lo})`; // Grün stabil hoch, Rot fällt
case 2: return `rgb(${lo}, ${hi}, ${rise})`; // Grün stabil hoch, Blau steigt
case 3: return `rgb(${lo}, ${fall}, ${hi})`; // Blau stabil hoch, Grün fällt
case 4: return `rgb(${rise}, ${lo}, ${hi})`; // Blau stabil hoch, Rot steigt
case 5: return `rgb(${hi}, ${lo}, ${fall})`; // Rot stabil hoch, Blau fällt
}
}
// Vergleich:
console.log(hsToRgb(0, 100)); // "rgb(255, 0, 0)" (Klassisches Rot)
console.log(hsToRgb(0, 50)); // "rgb(191, 64, 64)" (Blasses Rot)
console.log(hsToRgb(0, 0)); // "rgb(128, 128, 128)" (Grau - alle Kanäle gleich)
Hier ist der finale Schritt. Um die Helligkeit (L) zu integrieren, müssen wir das „Fenster“ (die Werte für high und low) vertikal verschieben.
Berechnung der Range: Wie stark weichen die Farben voneinander ab?
Die Range ist bei 50% Helligkeit am größten und wird zu 0% und 100% hin kleiner.
function hslToRgb(h, s, l) {
h = h % 360;
s /= 100;
l /= 100;
// Berechnung der Range: Wie stark weichen die Farben voneinander ab?
// Die Range ist bei 50% Helligkeit am größten und wird zu 0% und 100% hin kleiner.
const range = s * (1 - Math.abs(2 * l - 1));
const high = (l + range / 2) * 255;
const low = (l - range / 2) * 255;
const sector = Math.floor(h / 60);
const fraction = (h / 60) - sector;
const rise = Math.round(low + (high - low) * fraction);
const fall = Math.round(high - (high - low) * fraction);
const hi = Math.round(high);
const lo = Math.round(low);
switch(sector) {
case 0: return `rgb(${hi}, ${rise}, ${lo})`; // Rot-Gelb
case 1: return `rgb(${fall}, ${hi}, ${lo})`; // Gelb-Grün
case 2: return `rgb(${lo}, ${hi}, ${rise})`; // Grün-Cyan
case 3: return `rgb(${lo}, ${fall}, ${hi})`; // Cyan-Blau
case 4: return `rgb(${rise}, ${lo}, ${hi})`; // Blau-Magenta
case 5: return `rgb(${hi}, ${lo}, ${fall})`; // Magenta-Rot
}
}
// Tests:
console.log(hslToRgb(0, 100, 50)); // "rgb(255, 0, 0)" (Reines Rot)
console.log(hslToRgb(0, 100, 25)); // "rgb(128, 0, 0)" (Dunkelrot)
console.log(hslToRgb(0, 100, 75)); // "rgb(255, 128, 128)" (Hellrot/Rosa)
console.log(hslToRgb(0, 0, 50)); // "rgb(128, 128, 128)" (Grau)