Anwenden von Stil- und Farbeffekten
Im Kapitel über das Zeichnen von Formen haben wir nur die Standardlinien- und Füllstile verwendet. Hier werden wir die Canvas-Optionen untersuchen, die uns zur Verfügung stehen, um unsere Zeichnungen etwas attraktiver zu gestalten. Sie werden lernen, wie Sie Ihren Zeichnungen verschiedene Farben, Linienstile, Verläufe, Muster und Schatten hinzufügen können.
Hinweis:
Canvas-Inhalte sind für Bildschirmleser nicht zugänglich. Wenn das Canvas rein dekorativ ist, fügen Sie dem <canvas>
-Eröffnungstag role="presentation"
hinzu. Andernfalls fügen Sie beschreibenden Text als Wert des aria-label
-Attributs direkt zum Canvas-Element selbst oder platzieren Sie Fallback-Inhalte innerhalb des öffnenden und schließenden Canvas-Tags. Canvas-Inhalte sind nicht Teil des DOM, aber verschachtelte Fallback-Inhalte schon.
Farben
Bisher haben wir nur Methoden des Zeichenkontexts gesehen. Wenn wir Formen Farben zuweisen möchten, gibt es zwei wichtige Eigenschaften, die wir verwenden können: fillStyle
und strokeStyle
.
fillStyle = color
-
Legt den Stil fest, der beim Füllen von Formen verwendet wird.
strokeStyle = color
-
Legt den Stil für die Umrisse von Formen fest.
color
ist ein String, der ein CSS <color>
, ein Verlaufsobjekt oder ein Musterobjekt darstellt. Wir werden später auf Verlaufs- und Musterobjekte eingehen. Standardmäßig sind die Strich- und Füllfarben auf Schwarz (CSS-Farbwert #000000
) eingestellt.
Hinweis:
Wenn Sie die Eigenschaft strokeStyle
und/oder fillStyle
festlegen, wird der neue Wert zum Standard für alle danach gezeichneten Formen. Für jede Form, die Sie in einer anderen Farbe haben möchten, müssen Sie die Eigenschaft fillStyle
oder strokeStyle
neu zuweisen.
Die gültigen Strings, die Sie eingeben können, sollten entsprechend der Spezifikation CSS-<color>
-Werte sein. Jedes der folgenden Beispiele beschreibt die gleiche Farbe.
// these all set the fillStyle to 'orange'
ctx.fillStyle = "orange";
ctx.fillStyle = "#FFA500";
ctx.fillStyle = "rgb(255 165 0)";
ctx.fillStyle = "rgb(255 165 0 / 100%)";
Ein fillStyle
-Beispiel
In diesem Beispiel verwenden wir erneut zwei for
-Schleifen, um ein Gitter mit Rechtecken zu zeichnen, die jeweils in einer anderen Farbe sind. Das resultierende Bild sollte ungefähr wie der Screenshot aussehen. Es passiert hier nichts allzu Spektakuläres. Wir verwenden die zwei Variablen i
und j
, um eine eindeutige RGB-Farbe für jedes Quadrat zu generieren, und ändern nur die roten und grünen Werte. Der blaue Kanal hat einen festen Wert. Durch die Modifikation der Kanäle können Sie alle Arten von Paletten erzeugen. Durch Erhöhen der Schritte können Sie etwas erreichen, das wie die Farbpaletten von Photoshop aussieht.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
for (let i = 0; i < 6; i++) {
for (let j = 0; j < 6; j++) {
ctx.fillStyle = `rgb(${Math.floor(255 - 42.5 * i)} ${Math.floor(
255 - 42.5 * j,
)} 0)`;
ctx.fillRect(j * 25, i * 25, 25, 25);
}
}
}
Das Ergebnis sieht so aus:
Ein strokeStyle
-Beispiel
Dieses Beispiel ist dem obigen ähnlich, aber es verwendet die Eigenschaft strokeStyle
, um die Farben der Umrisse der Formen zu ändern. Wir verwenden die Methode arc()
, um Kreise anstelle von Quadraten zu zeichnen.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
for (let i = 0; i < 6; i++) {
for (let j = 0; j < 6; j++) {
ctx.strokeStyle = `rgb(0 ${Math.floor(255 - 42.5 * i)} ${Math.floor(
255 - 42.5 * j,
)})`;
ctx.beginPath();
ctx.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, 2 * Math.PI, true);
ctx.stroke();
}
}
}
Das Ergebnis sieht so aus:
Transparenz
Zusätzlich zum Zeichnen von opaken Formen auf das Canvas können wir auch halbtransparente (oder durchscheinende) Formen zeichnen. Dies geschieht entweder durch Festlegen der Eigenschaft globalAlpha
oder durch Zuweisen einer halbtransparenten Farbe zu den Strich- und/oder Füllstilen.
globalAlpha = transparencyValue
-
Wendet den angegebenen Transparenzwert auf alle zukünftigen Formen an, die auf das Canvas gezeichnet werden. Der Wert muss zwischen 0,0 (vollständig transparent) und 1,0 (vollständig opak) liegen. Dieser Wert ist standardmäßig 1,0 (vollständig opak).
Die Eigenschaft globalAlpha
kann nützlich sein, wenn Sie viele Formen auf das Canvas mit ähnlicher Transparenz zeichnen möchten. Andernfalls ist es jedoch im Allgemeinen nützlicher, die Transparenz für einzelne Formen festzulegen, wenn Sie deren Farben einstellen.
Da die Eigenschaften strokeStyle
und fillStyle
CSS-RGB-Farbwerte akzeptieren, können wir die folgende Notation verwenden, um ihnen eine transparente Farbe zuzuweisen.
// Assigning transparent colors to stroke and fill style
ctx.strokeStyle = "rgb(255 0 0 / 50%)";
ctx.fillStyle = "rgb(255 0 0 / 50%)";
Die Funktion rgb()
hat einen optionalen zusätzlichen Parameter. Der letzte Parameter setzt den Transparenzwert dieser bestimmten Farbe. Der gültige Bereich wird entweder als Prozentsatz zwischen 0%
(vollständig transparent) und 100%
(vollständig opak) oder als Zahl zwischen 0.0
(entspricht 0%
) und 1.0
(entspricht 100%
) angegeben.
Ein globalAlpha
-Beispiel
In diesem Beispiel zeichnen wir einen Hintergrund aus vier unterschiedlich farbigen Quadraten. Darüber werden wir eine Reihe von halbtransparenten Kreisen zeichnen. Die Eigenschaft globalAlpha
wird auf 0.2
gesetzt, die für alle Formen von diesem Punkt an verwendet wird. Jeder Schritt in der for
-Schleife zeichnet eine Reihe von Kreisen mit einem zunehmenden Radius. Das Endergebnis ist ein radialer Verlauf. Indem immer mehr Kreise übereinander gelegt werden, reduzieren wir effektiv die Transparenz der bereits gezeichneten Kreise. Durch Erhöhung der Schrittanzahl und das Zeichnen weiterer Kreise würde der Hintergrund vollständig aus dem Zentrum des Bildes verschwinden.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// draw background
ctx.fillStyle = "#ffdd00";
ctx.fillRect(0, 0, 75, 75);
ctx.fillStyle = "#66cc00";
ctx.fillRect(75, 0, 75, 75);
ctx.fillStyle = "#0099ff";
ctx.fillRect(0, 75, 75, 75);
ctx.fillStyle = "#ff3300";
ctx.fillRect(75, 75, 75, 75);
ctx.fillStyle = "white";
// set transparency value
ctx.globalAlpha = 0.2;
// Draw semi transparent circles
for (let i = 0; i < 7; i++) {
ctx.beginPath();
ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true);
ctx.fill();
}
}
Ein Beispiel mit rgb()
mit Alphatransparenz
In diesem zweiten Beispiel machen wir etwas Ähnliches wie oben, aber anstatt Kreise übereinander zu zeichnen, habe ich kleine Rechtecke mit zunehmender Opazität gezeichnet. Die Verwendung von rgb()
bietet Ihnen ein wenig mehr Kontrolle und Flexibilität, da wir den Füll- und Strichstil individuell festlegen können.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Draw background
ctx.fillStyle = "rgb(255 221 0)";
ctx.fillRect(0, 0, 150, 37.5);
ctx.fillStyle = "rgb(102 204 0)";
ctx.fillRect(0, 37.5, 150, 37.5);
ctx.fillStyle = "rgb(0 153 255)";
ctx.fillRect(0, 75, 150, 37.5);
ctx.fillStyle = "rgb(255 51 0)";
ctx.fillRect(0, 112.5, 150, 37.5);
// Draw semi transparent rectangles
for (let i = 0; i < 10; i++) {
ctx.fillStyle = `rgb(255 255 255 / ${(i + 1) / 10})`;
for (let j = 0; j < 4; j++) {
ctx.fillRect(5 + i * 14, 5 + j * 37.5, 14, 27.5);
}
}
}
Linienstile
Es gibt mehrere Eigenschaften, die es uns ermöglichen, Linien zu gestalten.
lineWidth = value
-
Legt die Breite der in Zukunft gezeichneten Linien fest.
lineCap = type
-
Bestimmt das Aussehen der Enden von Linien.
lineJoin = type
-
Legt das Aussehen der "Ecken" fest, an denen Linien zusammentreffen.
miterLimit = value
-
Legt ein Limit für das Miter fest, wenn zwei Linien in einem scharfen Winkel zusammentreffen, sodass Sie steuern können, wie dick die Verbindung wird.
getLineDash()
-
Gibt das aktuelle Linen-Dash-Musterarray zurück, das eine gerade Anzahl nicht-negativer Zahlen enthält.
setLineDash(segments)
-
Legt das aktuelle Linen-Dash-Muster fest.
lineDashOffset = value
-
Gibt an, wo ein Dash-Array auf einer Linie beginnt.
Sie werden ein besseres Verständnis dafür bekommen, was diese tun, indem Sie sich die folgenden Beispiele ansehen.
Ein lineWidth
-Beispiel
Diese Eigenschaft legt die aktuelle Linienstärke fest. Werte müssen positive Zahlen sein. Standardmäßig ist dieser Wert auf 1,0 Einheiten eingestellt.
Die Linienbreite ist die Dicke des Strichs, die auf dem gegebenen Pfad zentriert ist. Mit anderen Worten erstreckt sich der gezeichnete Bereich um die Hälfte der Linienbreite auf beiden Seiten des Pfades. Da Canvas-Koordinaten nicht direkt auf Pixel verweisen, muss besondere Vorsicht walten, um klare horizontale und vertikale Linien zu erhalten.
Im Beispiel unten werden 10 gerade Linien mit zunehmender Linienbreite gezeichnet. Die Linie ganz links ist 1,0 Einheiten breit. Allerdings erscheinen die ganz links und alle anderen ungeraden Integer-breiten Linien nicht scharf, aufgrund der Positionierung des Pfades.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
for (let i = 0; i < 10; i++) {
ctx.lineWidth = 1 + i;
ctx.beginPath();
ctx.moveTo(5 + i * 14, 5);
ctx.lineTo(5 + i * 14, 140);
ctx.stroke();
}
}
Hinweis: Wenn Sie sich über die Linien wundern, die in der Nähe der Kante statt Schwarz grau erscheinen, sehen Sie sich den Abschnitt Verschwommene Kanten sehen? im vorherigen Kapitel an.
Ein lineCap
-Beispiel
Die Eigenschaft lineCap
bestimmt, wie die Endpunkte jeder Linie gezeichnet werden. Es gibt drei mögliche Werte für diese Eigenschaft: butt
, round
und square
. Standardmäßig ist diese Eigenschaft auf butt
eingestellt:
butt
-
Die Enden von Linien werden an den Endpunkten abgekappt.
round
-
Die Enden von Linien sind gerundet.
square
-
Die Enden von Linien werden durch Hinzufügen eines Kästchens mit gleicher Breite und halber Höhe der Linienstärke abgekappt.
Es sind nur die Start- und Endendpunkte eines Pfades betroffen: Wenn ein Pfad mit closePath()
geschlossen wird, gibt es keinen Start- und Endendpunkt; stattdessen werden alle Endpunkte im Pfad mithilfe der aktuellen Einstellung des lineJoin
-Stils mit ihrem angehängten vorherigen und nächsten Segment verbunden.
In diesem Beispiel werden wir drei Linien zeichnen, jede mit einem anderen Wert für die Eigenschaft lineCap
. Ich habe auch zwei Leitlinien hinzugefügt, um die genauen Unterschiede zwischen den drei zu sehen. Jede dieser Linien beginnt und endet genau auf diesen Leitlinien.
Die Linie links verwendet die Standardoption butt
. Sie werden bemerken, dass sie vollständig bündig mit den Leitlinien gezeichnet ist. Die zweite ist so eingestellt, dass sie die Option round
verwendet. Dies fügt dem Ende einen Halbkreis hinzu, der einen Radius von der Hälfte der Linienbreite hat. Die Linie rechts verwendet die Option square
. Dies fügt ein Kästchen mit gleicher Breite und halber Höhe der Linienstärke hinzu.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Draw guides
ctx.strokeStyle = "#0099ff";
ctx.beginPath();
ctx.moveTo(10, 10);
ctx.lineTo(140, 10);
ctx.moveTo(10, 140);
ctx.lineTo(140, 140);
ctx.stroke();
// Draw lines
ctx.strokeStyle = "black";
["butt", "round", "square"].forEach((lineCap, i) => {
ctx.lineWidth = 15;
ctx.lineCap = lineCap;
ctx.beginPath();
ctx.moveTo(25 + i * 50, 10);
ctx.lineTo(25 + i * 50, 140);
ctx.stroke();
});
}
Ein lineJoin
-Beispiel
Die Eigenschaft lineJoin
bestimmt, wie zwei verbindende Segmente (von Linien, Bögen oder Kurven) mit nicht-null-Längen in einer Form verbunden werden (degenerierte Segmente mit Null-Längen, deren angegebene Endpunkte und Kontrollpunkte genau an derselben Position liegen, werden übersprungen).
Es gibt drei mögliche Werte für diese Eigenschaft: round
, bevel
und miter
. Standardmäßig ist diese Eigenschaft auf miter
eingestellt. Beachten Sie, dass die Einstellung lineJoin
keine Wirkung hat, wenn die beiden verbundenen Segmente die gleiche Richtung haben, da in diesem Fall kein Verbindungsbereich hinzugefügt wird:
round
-
Rundet die Ecken einer Form ab, indem ein zusätzlicher Kreissektors gefüllt wird, der am gemeinsamen Endpunkt der verbundenen Segmente zentriert ist. Der Radius für diese abgerundeten Ecken entspricht der Hälfte der Linienbreite.
bevel
-
Füllt einen zusätzlichen dreieckigen Bereich zwischen dem gemeinsamen Endpunkt der verbundenen Segmente und den separaten äußeren rechteckigen Ecken jedes Segments.
miter
-
Verbundene Segmente werden verbunden, indem ihre äußeren Kanten bis zu einem einzigen Punkt verlängert werden, mit der Wirkung, dass ein zusätzlicher rautenförmiger Bereich gefüllt wird. Diese Einstellung wird durch die Eigenschaft
miterLimit
beeinflusst, die unten erläutert wird.
Das folgende Beispiel zeichnet drei unterschiedliche Pfade, die jede dieser drei lineJoin
-Eigenschaftseinstellungen demonstrieren; der Output wird oben angezeigt.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
ctx.lineWidth = 10;
["round", "bevel", "miter"].forEach((lineJoin, i) => {
ctx.lineJoin = lineJoin;
ctx.beginPath();
ctx.moveTo(-5, 5 + i * 40);
ctx.lineTo(35, 45 + i * 40);
ctx.lineTo(75, 5 + i * 40);
ctx.lineTo(115, 45 + i * 40);
ctx.lineTo(155, 5 + i * 40);
ctx.stroke();
});
}
Eine Demonstration der miterLimit
-Eigenschaft
Wie Sie im vorherigen Beispiel gesehen haben, werden beim Verbinden von zwei Linien mit der miter
-Option die äußeren Kanten der beiden verbündeten Linien bis zu dem Punkt verlängert, an dem sie sich treffen. Für Linien, die in großen Winkeln zueinander stehen, ist dieser Punkt nicht weit vom inneren Verbindungspunkt entfernt. Wenn jedoch die Winkel zwischen den Linien kleiner werden, nimmt der Abstand (Miterlänge) zwischen diesen Punkten exponentiell zu.
Die Eigenschaft miterLimit
bestimmt, wie weit der äußere Verbindungspunkt vom inneren Verbindungspunkt entfernt werden kann. Wenn zwei Linien diesen Wert überschreiten, wird stattdessen ein Fasenverbindung gezeichnet. Beachten Sie, dass die maximale Miterlänge das Produkt der Linienbreite, gemessen im aktuellen Koordinatensystem, mit dem Wert dieser miterLimit
-Eigenschaft (deren Standardwert in der HTML-<canvas>
10.0 beträgt) ist, sodass die miterLimit
unabhängig von dem aktuellen Anzeigefaktor oder jeglichen affinen Transformationen von Pfaden gesetzt werden kann: sie beeinflusst nur die effektiv gerenderte Form der Kanten von Linien.
Genauer gesagt ist das Miterlimit das maximal erlaubte Verhältnis der Verlängerungslänge (im HTML-Canvas wird es zwischen der äußeren Ecke der verbundenen Kanten der Linie und dem gemeinsamen Endpunkt der im Pfad angegebenen Verbindungspunkte gemessen) zur halben Linienbreite. Es kann gleichwertig als das maximal zulässige Verhältnis der Entfernung zwischen dem inneren und äußeren Punkt der Verbindung von Kanten zur gesamten Linienbreite definiert werden. Es entspricht dann dem Kosekanten-Halbwert des minimalen Innenwinkels der Verbindungspunkte unterhalb dessen keine Miterverbindung gerendert wird, sondern nur eine Fasenverbindung:
miterLimit
= maxmiterLength
/lineWidth
= 1 / sin ( min θ / 2 )- Das Standard-Miterlimit von 10,0 entfernt alle Miters für scharfe Winkel unter etwa 11 Grad.
- Ein Miterlimit von √2 ≈ 1,4142136 (aufgerundet) entfernt die Miter für alle spitzen Winkel und behält Miterverbindungen nur für stumpfe oder rechte Winkel.
- Ein Miterlimit von 1,0 ist gültig, entfernt jedoch alle Miters.
- Werte unter 1,0 sind für das Miterlimit ungültig.
Hier ist eine kleine Demo, in der Sie miterLimit
dynamisch festlegen können und sehen, wie sich dies auf die Formen auf dem Canvas auswirkt. Die blauen Linien zeigen, wo die Start- und Endpunkte für jede der Linien im Zick-Zack-Muster sind.
Wenn Sie in dieser Demo einen miterLimit
-Wert unter 4,2 angeben, wird keine der sichtbaren Ecken mit einer Mitererweiterung verbunden, sondern nur mit einer kleinen Fase in der Nähe der blauen Linien; mit einem miterLimit
über 10 sollten die meisten Ecken in dieser Demo mit einem Miter weit weg von den blauen Linien verbunden werden, dessen Höhe zwischen den Ecken von links nach rechts abnimmt, da sie mit wachsenden Winkeln verbunden sind; bei Zwischenwerten werden die Ecken auf der linken Seite nur mit einer Fase in der Nähe der blauen Linien verbunden, und die Ecken auf der rechten Seite mit einer Mitererweiterung (ebenfalls mit abnehmender Höhe).
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Clear canvas
ctx.clearRect(0, 0, 150, 150);
// Draw guides
ctx.strokeStyle = "#0099ff";
ctx.lineWidth = 2;
ctx.strokeRect(-5, 50, 160, 50);
// Set line styles
ctx.strokeStyle = "black";
ctx.lineWidth = 10;
// check input
if (document.getElementById("miterLimit").checkValidity()) {
ctx.miterLimit = parseFloat(document.getElementById("miterLimit").value);
}
// Draw lines
ctx.beginPath();
ctx.moveTo(0, 100);
for (let i = 0; i < 24; i++) {
const dy = i % 2 === 0 ? 25 : -25;
ctx.lineTo(i ** 1.5 * 2, 75 + dy);
}
ctx.stroke();
return false;
}
Verwendung von Liniendashes
Die Methode setLineDash
und die Eigenschaft lineDashOffset
spezifizieren das Dash-Muster für Linien. Die Methode setLineDash
akzeptiert eine Liste von Zahlen, die Abstände zum abwechselnden Zeichnen einer Linie und einer Lücke angibt, und die Eigenschaft lineDashOffset
setzt einen Versatz, bei dem das Muster beginnt.
In diesem Beispiel erstellen wir einen "marching ants"-Effekt. Es ist eine Animationstechnik, die häufig in Auswahlwerkzeugen von Computergraphikprogrammen zu finden ist. Sie hilft dem Benutzer, die Auswahlgrenze vom Bildhintergrund zu unterscheiden, indem sie die Grenze animiert. In einem späteren Teil dieses Tutorials können Sie lernen, wie Sie dies und andere grundlegende Animationen durchführen.
const ctx = document.getElementById("canvas").getContext("2d");
let offset = 0;
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.setLineDash([4, 2]);
ctx.lineDashOffset = -offset;
ctx.strokeRect(10, 10, 100, 100);
}
function march() {
offset++;
if (offset > 5) {
offset = 0;
}
draw();
setTimeout(march, 20);
}
march();
Verläufe
Genau wie in einem normalen Zeichenprogramm können wir Formen mit linearen, radialen und konischen Verläufen füllen und umranden. Wir erstellen ein CanvasGradient
-Objekt, indem wir eine der folgenden Methoden verwenden. Wir können dieses Objekt dann den Eigenschaften fillStyle
oder strokeStyle
zuweisen.
createLinearGradient(x1, y1, x2, y2)
-
Erstellt ein lineares Verlaufsobjekt mit einem Startpunkt von (
x1
,y1
) und einem Endpunkt von (x2
,y2
). createRadialGradient(x1, y1, r1, x2, y2, r2)
-
Erstellt einen radialen Verlauf. Die Parameter repräsentieren zwei Kreise, einer mit seinem Zentrum bei (
x1
,y1
) und einem Radius vonr1
, und der andere mit seinem Zentrum bei (x2
,y2
) mit einem Radius vonr2
. createConicGradient(angle, x, y)
-
Erstellt ein konisches Verlaufsobjekt mit einem Startwinkel von
angle
in Radianten an der Position (x
,y
).
Zum Beispiel:
const lineargradient = ctx.createLinearGradient(0, 0, 150, 150);
const radialgradient = ctx.createRadialGradient(75, 75, 0, 75, 75, 100);
Sobald wir ein CanvasGradient
-Objekt erstellt haben, können wir mithilfe der Methode addColorStop()
Farben zuweisen.
gradient.addColorStop(position, color)
-
Erstellt einen neuen Farbstop auf dem
gradient
-Objekt. Dieposition
ist eine Zahl zwischen 0.0 und 1.0 und definiert die relative Position der Farbe im Verlauf, und dascolor
-Argument muss ein String sein, der ein CSS<color>
darstellt, der die Farbe angibt, die der Verlauf an diesem Offset in den Übergang erreichen soll.
Sie können einem Verlauf so viele Farbstopps hinzufügen, wie Sie benötigen. Unten ist ein sehr einfacher linearer Verlauf von Weiß zu Schwarz.
const lineargradient = ctx.createLinearGradient(0, 0, 150, 150);
lineargradient.addColorStop(0, "white");
lineargradient.addColorStop(1, "black");
Ein createLinearGradient
-Beispiel
In diesem Beispiel erstellen wir zwei verschiedene Verläufe. Wie Sie hier sehen können, können sowohl die Eigenschaften strokeStyle
als auch fillStyle
ein canvasGradient
-Objekt als gültigen Eingang akzeptieren.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Create gradients
const linGrad = ctx.createLinearGradient(0, 0, 0, 150);
linGrad.addColorStop(0, "#00ABEB");
linGrad.addColorStop(0.5, "white");
linGrad.addColorStop(0.5, "#26C000");
linGrad.addColorStop(1, "white");
const linGrad2 = ctx.createLinearGradient(0, 50, 0, 95);
linGrad2.addColorStop(0.5, "black");
linGrad2.addColorStop(1, "transparent");
// assign gradients to fill and stroke styles
ctx.fillStyle = linGrad;
ctx.strokeStyle = linGrad2;
// draw shapes
ctx.fillRect(10, 10, 130, 130);
ctx.strokeRect(50, 50, 50, 50);
}
Der erste ist ein Hintergrundverlauf. Wie Sie sehen können, haben wir zwei Farben an derselben Position zugewiesen. Sie tun dies, um sehr scharfe Farbübergänge zu erzeugen, in diesem Fall von Weiß zu Grün. Normalerweise spielt es keine Rolle, in welcher Reihenfolge Sie die Farbstopps definieren, aber in diesem speziellen Fall ist es bedeutend. Wenn Sie die Zuweisungen in der Reihenfolge belassen, in der Sie sie erscheinen lassen möchten, wird dies kein Problem darstellen.
Beim zweiten Verlauf haben wir die Startfarbe (an Position 0.0) nicht zugewiesen, da dies nicht unbedingt erforderlich war, da sie automatisch die Farbe des nächsten Farbstopps annimmt. Daher macht die Zuweisung der schwarzen Farbe an Position 0.5 den Verlauf automatisch von Anfang bis zu diesem Stopp schwarz.
Ein createRadialGradient
-Beispiel
In diesem Beispiel definieren wir vier verschiedene radiale Verläufe. Da wir über Anfangs- und Endpunkte des Verlaufs Kontrolle haben, können wir komplexere Effekte erzielen, als wir normalerweise in den "klassischen" radialen Verläufen sehen, wie sie beispielsweise in Photoshop verwendet werden (d.h. ein Verlauf mit einem einzigen Mittelpunkt, von dem aus der Verlauf in kreisförmiger Form expandiert).
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Create gradients
const radGrad = ctx.createRadialGradient(45, 45, 10, 52, 50, 30);
radGrad.addColorStop(0, "#A7D30C");
radGrad.addColorStop(0.9, "#019F62");
radGrad.addColorStop(1, "transparent");
const radGrad2 = ctx.createRadialGradient(105, 105, 20, 112, 120, 50);
radGrad2.addColorStop(0, "#FF5F98");
radGrad2.addColorStop(0.75, "#FF0188");
radGrad2.addColorStop(1, "transparent");
const radGrad3 = ctx.createRadialGradient(95, 15, 15, 102, 20, 40);
radGrad3.addColorStop(0, "#00C9FF");
radGrad3.addColorStop(0.8, "#00B5E2");
radGrad3.addColorStop(1, "transparent");
const radGrad4 = ctx.createRadialGradient(0, 150, 50, 0, 140, 90);
radGrad4.addColorStop(0, "#F4F201");
radGrad4.addColorStop(0.8, "#E4C700");
radGrad4.addColorStop(1, "transparent");
// draw shapes
ctx.fillStyle = radGrad4;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radGrad3;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radGrad2;
ctx.fillRect(0, 0, 150, 150);
ctx.fillStyle = radGrad;
ctx.fillRect(0, 0, 150, 150);
}
In diesem Fall haben wir den Startpunkt leicht vom Endpunkt versetzt, um einen sphärischen 3D-Effekt zu erzielen. Es ist am besten zu vermeiden, dass sich die inneren und äußeren Kreise überlappen, da dies zu seltsamen Effekten führt, die schwer vorherzusagen sind.
Der letzte Farbverlauf in jedem der vier Verläufe verwendet eine vollständig transparente Farbe. Wenn Sie einen schönen Übergang von diesem zu dem vorherigen Farbverlauf haben möchten, sollten beide Farben gleich sein. Dies ist im Code nicht sehr offensichtlich, da es zwei verschiedene CSS-Farbmethoden als Demonstration verwendet, aber im ersten Verlauf #019F62 = rgb(1 159 98 / 100%)
.
Ein createConicGradient
-Beispiel
In diesem Beispiel definieren wir zwei verschiedene konische Verläufe. Ein konischer Verlauf unterscheidet sich von einem radialen Verlauf dadurch, dass er sich nicht um Kreise, sondern um einen Punkt dreht.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// Create gradients
const conicGrad1 = ctx.createConicGradient(2, 62, 75);
conicGrad1.addColorStop(0, "#A7D30C");
conicGrad1.addColorStop(1, "white");
const conicGrad2 = ctx.createConicGradient(0, 187, 75);
// we multiply our values by Math.PI/180 to convert degrees to radians
conicGrad2.addColorStop(0, "black");
conicGrad2.addColorStop(0.25, "black");
conicGrad2.addColorStop(0.25, "white");
conicGrad2.addColorStop(0.5, "white");
conicGrad2.addColorStop(0.5, "black");
conicGrad2.addColorStop(0.75, "black");
conicGrad2.addColorStop(0.75, "white");
conicGrad2.addColorStop(1, "white");
// draw shapes
ctx.fillStyle = conicGrad1;
ctx.fillRect(12, 25, 100, 100);
ctx.fillStyle = conicGrad2;
ctx.fillRect(137, 25, 100, 100);
}
Der erste Verlauf ist in der Mitte des ersten Rechtecks positioniert und bewegt einen grünen Farbverlaufstopp zu Beginn zu einem weißen am Ende. Der Winkel beginnt bei 2 Radianten, was erkennbar ist, da die Anfangs-/Endlinie nach Südosten zeigt.
Der zweite Verlauf ist ebenfalls in der Mitte des zweiten Rechtecks positioniert. Dieser hat mehrere Farbverläufe, die abwechselnd von Schwarz zu Weiß bei jedem Viertel der Rotation führen. Dies gibt uns den karierten Effekt.
Muster
In einem der Beispiele auf der vorherigen Seite haben wir eine Reihe von Schleifen verwendet, um ein Muster aus Bildern zu erstellen. Es gibt jedoch eine viel einfachere Methode: die Methode createPattern()
.
createPattern(image, type)
-
Erstellt und gibt ein neues Canvasmuster-Objekt zurück.
image
ist die Quelle des Bildes (d.h. einHTMLImageElement
, einSVGImageElement
, ein anderesHTMLCanvasElement
oder einOffscreenCanvas
, einHTMLVideoElement
oder einVideoFrame
, oder einImageBitmap
).type
ist ein String, der angibt, wie das Bild verwendet werden soll.
Der Typ gibt an, wie das Bild verwendet werden soll, um das Muster zu erstellen, und muss einer der folgenden Stringwerte sein:
repeat
-
Kachelt das Bild in beiden vertikalen und horizontalen Richtungen.
repeat-x
-
Kachelt das Bild horizontal, aber nicht vertikal.
repeat-y
-
Kachelt das Bild vertikal, aber nicht horizontal.
no-repeat
-
Kachelt das Bild nicht. Es wird nur einmal verwendet.
Wir verwenden diese Methode, um ein CanvasPattern
-Objekt zu erstellen, das den Gradientmethoden oben sehr ähnlich ist. Sobald wir ein Muster erstellt haben, können wir es den Eigenschaften fillStyle
oder strokeStyle
zuweisen. Zum Beispiel:
const img = new Image();
img.src = "some-image.png";
const pattern = ctx.createPattern(img, "repeat");
Hinweis:
Wie bei der Methode drawImage()
müssen Sie sicherstellen, dass das verwendete Bild geladen ist, bevor Sie diese Methode aufrufen, andernfalls wird das Muster möglicherweise nicht korrekt gezeichnet.
Ein createPattern
-Beispiel
In diesem letzten Beispiel erstellen wir ein Muster, das der Eigenschaft fillStyle
zugewiesen wird. Das einzige, was erwähnenswert ist, ist die Verwendung des onload
-Handlers des Bildes. Dies stellt sicher, dass das Bild geladen ist, bevor es dem Muster zugewiesen wird.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
// create new image object to use as pattern
const img = new Image();
img.src = "canvas_create_pattern.png";
img.onload = () => {
// create pattern
const pattern = ctx.createPattern(img, "repeat");
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, 150, 150);
};
}
Schatten
Die Verwendung von Schatten umfasst nur vier Eigenschaften:
shadowOffsetX = float
-
Gibt die horizontale Entfernung an, die der Schatten vom Objekt ausreichen soll. Dieser Wert wird nicht von der Transformationsmatrix beeinflusst. Der Standardwert ist 0.
shadowOffsetY = float
-
Gibt die vertikale Entfernung an, die der Schatten vom Objekt ausreichen soll. Dieser Wert wird nicht von der Transformationsmatrix beeinflusst. Der Standardwert ist 0.
shadowBlur = float
-
Gibt die Größe des Weichzeichnungseffekts an; dieser Wert entspricht nicht einer Anzahl von Pixeln und wird von der aktuellen Transformationsmatrix nicht beeinflusst. Der Standardwert ist 0.
shadowColor = color
-
Ein Standard-CSS-Farbwert, der die Farbe des Schatteneffekts angibt; standardmäßig ist es vollständig transparentes Schwarz.
Die Eigenschaften shadowOffsetX
und shadowOffsetY
geben an, wie weit der Schatten vom Objekt in X- und Y-Richtung ausgedehnt werden soll; diese Werte werden von der aktuellen Transformationsmatrix nicht beeinflusst. Verwenden Sie negative Werte, um den Schatten nach oben oder nach links zu verschieben, und positive Werte, um den Schatten nach unten oder nach rechts zu verschieben. Beide sind standardmäßig auf 0 gesetzt.
Die Eigenschaft shadowBlur
gibt die Größe des Weichzeichnungseffekts an; dieser Wert entspricht nicht einer Anzahl von Pixeln und wird von der aktuellen Transformationsmatrix nicht beeinflusst. Der Standardwert ist 0.
Die Eigenschaft shadowColor
ist ein standardmäßiger CSS-Farbwert, der die Farbe des Schatteneffekts angibt; standardmäßig ist es vollständig transparentes Schwarz.
Hinweis:
Schatten werden nur für source-over
Compositing-Operationen gezeichnet.
Ein Beispiel für beschatteten Text
Dieses Beispiel zeichnet eine Textzeichenfolge mit einem Schattierungseffekt.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
ctx.shadowOffsetX = 2;
ctx.shadowOffsetY = 2;
ctx.shadowBlur = 2;
ctx.shadowColor = "rgb(0 0 0 / 50%)";
ctx.font = "20px Times New Roman";
ctx.fillStyle = "Black";
ctx.fillText("Sample String", 5, 30);
}
Wir werden uns die font
-Eigenschaft und die Methode fillText
im nächsten Kapitel über das Zeichnen von Text ansehen.
Regeln zur Canvasfüllung
Beim Verwenden von fill
(oder clip
und isPointInPath
) können Sie optional einen Füllregel-Algorithmus angeben, um zu bestimmen, ob ein Punkt innerhalb oder außerhalb eines Pfades liegt und somit gefüllt wird oder nicht. Dies ist nützlich, wenn sich ein Pfad selbst schneidet oder verschachtelt ist.
Zwei Werte sind möglich:
nonzero
-
Die Nonzero-Regel, die Standardregel.
evenodd
-
Die Even-odd-Regel.
In diesem Beispiel verwenden wir die evenodd
-Regel.
function draw() {
const ctx = document.getElementById("canvas").getContext("2d");
ctx.beginPath();
ctx.arc(50, 50, 30, 0, Math.PI * 2, true);
ctx.arc(50, 50, 15, 0, Math.PI * 2, true);
ctx.fill("evenodd");
}