Farben im Canvas

Wir haben mit unserem Canvas die Möglichkeit alle gezeichneten Pfade, Kurven, Objekte und Formen mit Farbe zu versehen. Damit wir uns jedoch nicht auf die einfachen Farben beschränken müssen, sollten wir uns hier ein wenig näher mit dem Thema Farben im Canvas beschäftigen.

Einen Farbwert können wir mithilfe von sechs unterschiedlichen Techniken angeben:

MethodeBeispiel 1Beispiel 2
Vordefinierter Farbwertreddarkcyan
Hexadezimaler Farbwert#F00#008B8B
RGB-Funktions Farbwertrgb(255,0,0)rgb(0,139,139)
RGBA-Funktions Farbwertrgba(255,0,0,.8)rgba(0,139,139,.4)
HSL-Funktions Farbwertrgba(255,0,0,.8)rgba(0,139,139,.4)
HSLA-Funktions Farbwertrgba(255,0,0,.8)rgba(0,139,139,.4)

Mit vordefinierten Farbwerten können wir uns auf eine riesige Menge an Farbwertnamen berufen, die alle samt vordefinierte Farbwerte mit sich bringen. Beispielsweise definiert der Farbname red die Farbe Rot mit dem hexadezimalen Farbwert #FF0000. Doch wir müssen bei den vordefinierten Farbwerten vorsichtig sein, denn das Internet zeigt gerne Farbnamen, die nur bestimmte Browser anzeigen können. Die offizielle Spezifikation von CSS3 definiert zunächst folgende Basis-Farbnamen:

The list of basic color keywords is: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow. The color names are case-insensitive.

Die Liste der grundlegenden Schlüsselwörter für Farben ist: aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow. Die Groß- und Kleinschreibung der Namen ist egal.

Zu den erweiterten Farbnamen zählen laut Spezifikation die sogenannten "X11 Farben", welche die Grundfarben mit einschließen und damit insgesamt 140 Farben definieren.

Für die Verwendung müssen wir lediglich das Schlüsselwort der Farbe angeben:

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "darkcyan"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Mit den hexadezimalen Farbwerten können wir selbstverständlich noch wesentlich mehr Farben darstellen, als mit den vordefinierten Farben. Eine hexadezimale Darstellung von Farben besteht immer aus einer Raute (# gefolgt von drei oder sechs Hexadezimalzahlen.

Angegeben werden die drei Farben Rot, Grün und Blau. Somit wird der Code in drei gleichgroße Bereiche eingeteilt. Bei sechs Zahlen bedeutet das zwei Zahlen pro Farbanteil und bei drei Zahlen bedeutet das eine Zahl pro Farbanteil. Dazu ein Beispiel:

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "#008B8B"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Der hexadezimale Farbcode #008B8B wird mit einer Raute eingeleitet. Diese muss gesetzt sein, damit der Parser weiß, dass es sich um einen Farbcode handelt. Als nächstes wird der Code in drei gleichgroße Bereiche aufgeteilt:

  • Rot: 00
  • Grün: 8B
  • Blau: 8B

Der Computer mischt also eine Farbe, in der kein Anteil an Rot, und zwei gleichmäßige Anteile von Grün und Blau vorkommen. Das wir hier ein Cyan-Farbton herausbekommen können wir uns nun besser vorstellen. Wollen wir mehr in die türkise Richtung gehen, so benötigen wir auch mehr Grünanteile. Also könnten wir die hexadezimale Zahl für Grün einfach in ihrer Wertigkeit erhöhen.

  • Rot: 00
  • Grün: FF
  • Blau: 8B
  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "#00FF8B"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Haben wir einen Code der zwei gleiche Hexadezimalzahlen pro Farbanteil definiert, können wir diesen abkürzen, indem wir nur noch drei Zahlen setzen:

  • #33FFBB -> #33 FF BB kann zu #3FB abgekürzt werden
  • #CC77FF -> #CC 77 FF kann zu #C7F abgekürzt werden

Vorsicht ist jedoch geboten, sobald ein Farbton zwei unterschiedliche Zahlen besitzt:

  • #33FFBA -> #33 FF BA kann nicht zu #3FBA abgekürzt werden
  • #CE77FF -> #CE 77 FF kann nicht zu #CE7F abgekürzt werden

Mit der Funktion rgb( r, g, b ) können wir unsere Farbanteile ebenfalls zusammenmischen. Dafür geben wir in den drei Parametern die Farbanteile Rot, Grün und Blau mit einer Dezimalzahl an. Der Wert liegt zwischen 0 und 255, wobei 0 das Minimum und 255 das Maximum ist

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "rgb( 0, 139, 139 )"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Wollen wir nun auch noch die Transparenz berücksichtigen, brauchen wir die Funktion rgba( r, g, b, a ), welche als letzten Parameter eine Fließkommazahl von 0 bis 1 annimmt. Der Wert 0 bedeutet eine komplette Transparenz und somit, dass die Farbe nicht zu sehen ist. Der Wert 0.5 bedeutet, dass die Farbe halb durch scheinbar und somit mit dem dahinterliegenden Objekt gemischt wird. Der Wert 1 bedeutet demnach volle Deckkraft.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "rgba( 0, 139, 139, 0.3456 )"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Im obigen Beispiel sehen wir, wie unser Wert durch den sogenannten "Alphakanal" heller wird, denn wir haben diesen zu 34.56% transparent gemacht und deswegen mit der Hintergrundfarbe Weiß gemischt. Setzen wir die Hintergrundfarbe auf Schwarz, so würde der Strich dunkler wirken.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Hintergrundfarbe Schwarz rendern Context.fillStyle = "#000"; Context.fillRect( 0, 0, Canvas.width, Canvas.height ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "rgba( 0, 139, 139, 0.3456 )"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Als letztes gibt es noch die Methode hsl( h, s, l ). Die drei Zeichen sind die Anfangsbuchstaben der englischen Wörter hue, saturation und lightness, mit welchen wir den Farbton, die Sättigung und die Helligkeit setzen können. Die Werte dieser Funktion sind jedoch ein wenig komplizierter.

HSL - Farbkreis - CodingLab

Der Farbton ist eine Dezimalzahl von 0 bis 360. Wir haben hier also quasi einen Zeiger, den wir in einem Kreis mit Farben verschieben, wobei 0 (Grad) als Rot, 120 (Grad) als Grün und 240 (Grad) als Blau definiert ist.

Die Sättigung geben wir als Prozentsatz von 0 bis 100 an, wobei 0% keine Farbtonanteile bedeuten (Komplette Sättigung also ) und 100% der volle Farbton.

Bei der Helligkeit haben wir das umgekehrte Prinzip, wie bei der Sättigung: 0% bedeutet überhaupt keine Helligkeit also Schwarz und 100% bedeutet Weiß.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "hsl( 180, 100%, 27% )"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Im obigen Beispiel haben wir unseren "darkcyan" Farbton nachgebildet. Dafür haben wir zunächst auf dem Farbenkreis eine Gradzahl zwischen Grün und Blau genommen. Da 180 Grad genau die Mitte zwischen Grün und Blau darstellt haben wir auch wieder gleichviele Anteile beider Farben.

Da wir den vollen Farbton haben wollen, setzen wir die Sättigung auf 100%. Dabei muss das Prozentzeichen gesetzt werden.

Nun kommt die Helligkeit. Da wir ein eher dunkles Cyan als Farbton haben, setzen wir diese auf 27%.

Natürlich gibt es auch von dieser Funktion eine Variante mit dem Alphakanal. Diese heißt hsla( h, s, l, a ) und nimmt als letzten Parameter die Transparenz von 0 bis 1.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Eine diagonale Linie zeichnen Context.beginPath(); Context.lineWidth = "5"; Context.strokeStyle = "hsla( 180, 100%, 27%, 0.3456 )"; Context.moveTo( 10, 10 ); Context.lineTo( 590, 190 ); Context.stroke();

Linearer Farbverlauf

In unserem Canvas können wir zwei Arten von Farbverläufen abbilden:

  • createLinearGradient()
  • createRadialGradient()

Mit der Funktion createLinearGradient( x0, y0, x1, y1 ) können wir einen linearen Farbverlauf darstellen, wobei die Parameter folgendes bedeuten:

ParameterBeschreibung
x0X-Koordinate für den Startpunkt
y0Y-Koordinate für den Startpunkt
x1X-Koordinate für den Endpunkt
y1Y-Koordinate für den Endpunkt

Führen wir diese Funktion aus, gibt diese ein Objekt zurück, von dem wir die Funktion addColorStop( stop, color ) ausführen können. Diese nimmt als ersten Parameter eine Fließkommazahl von 0 bis 1, welche die Position zwischen Start und Ende des Verlaufs angibt. Der zweite Parameter ist die Farbe, wofür wir die uns bekannten Möglichkeiten für Farbangaben ausschöpfen können.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Farbverlauf - Daten eingeben var GradientObjekt = Context.createLinearGradient( 0, 0, Canvas.width, 0 ); GradientObjekt.addColorStop( 0, "#000" ); GradientObjekt.addColorStop( 1, "#FFF" ); //Farbverlauf - zeichnen Context.fillStyle = GradientObjekt; Context.fillRect( 0, 0, Canvas.width, Canvas.height );

Im obigen Beispiel haben wir einen Farbverlauf vom Startpunkt 0/0 bis zum Endpunkt 600/0 gezeichnet. Als Startpunkt haben wir die Farbe Schwarz mit der Funktion addColorStop() gesetzt. Deswegen haben wir den ersten Parameter mit 0 belegt. Als Zweites haben wir die Farbe Weiß mit der Position 1 - also Ende - gesetzt. Das Objekt, welches wir in der Variablen GradientObjekt gespeichert haben, müssen wir nun als FillStyle unseres Kontexts setzen und können anschließend einfach ein Rechteck mit unserem Verlauf zeichnen.

Als nächstes wollen wir einmal eine weitere Farbe in der Mitte einfügen. Dafür müssen wir lediglich die Funktion addColorStop() mit der Position 0.5 und unserer Farbe ausführen:

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Farbverlauf - Daten eingeben var GradientObjekt = Context.createLinearGradient( 0, 0, Canvas.width, 0 ); GradientObjekt.addColorStop( 0, "#000" ); GradientObjekt.addColorStop( 0.5, "#F00" ); GradientObjekt.addColorStop( 1, "#FFF" ); //Farbverlauf - zeichnen Context.fillStyle = GradientObjekt; Context.fillRect( 0, 0, Canvas.width, Canvas.height );

Radialer Farbverlauf

Um einen radialen Farbverlauf zu erstellen, müssen wir die Funktion createRadialGradient( x0, y0, r0, x1, y1, r1 ) ausführen. Diese nimmt vereinfacht gesagt die Parameter für zwei Kreise an:

ParameterBeschreibung
x0X-Koordinate für den ersten Kreis
y0Y-Koordinate für den ersten Kreis
r0Radius für den ersten Kreis
x1X-Koordinate für den zweiten Kreis
y1Y-Koordinate für den zweiten Kreis
r1Radius für den zweiten Kreis

Zwischen den beiden Kreisen wird nun der Farbverlauf dargestellt. Dabei können wir mit der Funktion addColorStop( stop, color ) die verschiedenen Farben angeben. Als ersten Parameter nimmt diese die Position der Farbe im Verlauf und als zweiten Parameter die Farbe.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Farbverlauf - Daten eingeben var xCenter = Canvas.width >> 1; var yCenter = Canvas.height >> 1; var GradientObjekt = Context.createRadialGradient( xCenter, yCenter, 100, xCenter, yCenter, 20 ); GradientObjekt.addColorStop( 0, "#FFF" ); GradientObjekt.addColorStop( 1, "#F00" ); //Farbverlauf - zeichnen Context.fillStyle = GradientObjekt; Context.fillRect( 0, 0, Canvas.width, Canvas.height );

Im obigen Beispiel sehen wir einen sehr kräftigen inneren Kreis in der Farbe Rot. Dieser fängt an sich mit der Farbe Weiß zu mischen und bildet so den Farbverlauf in der Größe des ersten Kreises. Je größer wir den zweiten Kreis machen, desto größer wird der kräftigere Innenkreis. Setzen wir den zweiten Radius auf 99, bekommen wir einen roten Kreis, da der Abstand zwischen den beiden Kreisen zu gering für einen Verlauf ist.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Farbverlauf - Daten eingeben var xCenter = Canvas.width >> 1; var yCenter = Canvas.height >> 1; var GradientObjekt = Context.createRadialGradient( xCenter, yCenter, 100, xCenter, yCenter, 99 ); GradientObjekt.addColorStop( 0, "#FFF" ); GradientObjekt.addColorStop( 1, "#F00" ); //Farbverlauf - zeichnen Context.fillStyle = GradientObjekt; Context.fillRect( 0, 0, Canvas.width, Canvas.height );

HSL-Kreis nachbilden

Als letztes wollen wir einmal den HSL-Farbkreis nachzeichnen. Die Farben, die wir dafür benötigen, können wir an dem obigen Bild ablesen und lauten: Rot, Gelb, Grün, Cyan, Blau und Magenta. Da wir einen linearen Farbverlauf nur in eine Richtung ziehen können, wir aber im Grunde genommen zwei brauchen, teilen wir unseren Kreis in zwei Hälften und benutzen zwei Farbverläufe. Wir müssen unseren Farbverlauf also in jeweils vier gleichmäßige Schritte einteilen, da wir auch vier Farben pro Hälfte anzeigen wollen.

Wesentlich wichtiger ist dabei, dass wir den Start- und Endpunkt des Verlaufs auch auf unsere Anzeigefläche des Kreises setzen. Wenn unser Kreis komplett mittig platziert ist und die gesamte Höhe einnimmt, müssen wir auch einen Farbverlauf von Mitte-Oben zum Boden ziehen und für die zweite Hälfte von unten nach oben. Anschließend zeichnen wir mit dem strokeStyle einfach unseren Kreis in der gewünschten Linienbreite.

wert >> 1 bedeutet einfach nur geteilt durch 2, da alle Bits nach rechts geshiftet werden. Dazu irgendwann anders mehr.

  • Html
  • Javascript
  • Ergebnis
<html> <head></head> <body> <canvas id="canvas_id" width="600" height="200" style="border: 1px solid red;"></canvas> </body> </html>
var Canvas = document.getElementById( "canvas_id" ); var Context = Canvas.getContext( "2d" ); //Farbverlauf erste Kreishälfte var GradientObjekt1 = Context.createLinearGradient( Canvas.width >> 1, 0, Canvas.width >> 1, Canvas.height ); GradientObjekt1.addColorStop( (1/4*1), "red" ); GradientObjekt1.addColorStop( (1/4*2), "yellow" ); GradientObjekt1.addColorStop( (1/4*3), "green" ); GradientObjekt1.addColorStop( (1/4*4), "cyan" ); //Farbverlauf zweite Kreishälfte var GradientObjekt2 = Context.createLinearGradient( Canvas.width >> 1, Canvas.height, Canvas.width >> 1, 0 ); GradientObjekt2.addColorStop( (1/4*1), "cyan" ); GradientObjekt2.addColorStop( (1/4*2), "blue" ); GradientObjekt2.addColorStop( (1/4*3), "magenta" ); GradientObjekt2.addColorStop( (1/4*4), "red" ); //Radius mit Linienbreite berechnen var LineWidth = 10; var Radius = (Math.min( Canvas.width, Canvas.height ) >> 1) - (LineWidth >> 1); //Erste Kreishälfte zeichnen Context.beginPath(); Context.lineWidth = LineWidth; Context.strokeStyle = GradientObjekt1; Context.arc( Canvas.width >> 1, Canvas.height >> 1, Radius, Math.PI * 1.5, Math.PI * 0.5, false ); Context.stroke(); //Zweite Kreishälfte zeichnen Context.beginPath(); Context.lineWidth = LineWidth; Context.strokeStyle = GradientObjekt2; Context.arc( Canvas.width >> 1, Canvas.height >> 1, Radius, Math.PI * 0.5, Math.PI * 1.5, false ); Context.stroke();