diff options
Diffstat (limited to 'files/de/web/api/css_painting_api')
-rw-r--r-- | files/de/web/api/css_painting_api/guide/index.html | 534 | ||||
-rw-r--r-- | files/de/web/api/css_painting_api/index.html | 199 |
2 files changed, 733 insertions, 0 deletions
diff --git a/files/de/web/api/css_painting_api/guide/index.html b/files/de/web/api/css_painting_api/guide/index.html new file mode 100644 index 0000000000..536040de4e --- /dev/null +++ b/files/de/web/api/css_painting_api/guide/index.html @@ -0,0 +1,534 @@ +--- +title: Die CSS Painting API verwenden +slug: Web/API/CSS_Painting_API/Guide +translation_of: Web/API/CSS_Painting_API/Guide +--- +<p>Die CSS Paint API wurde entworfen, um Entwicklern zu ermöglichen, programmatisch Bilder festzulegen, die überall dort verwendet werden können, wo ein CSS Bild aufgerufen werden kann, wie in CSS <code><a href="/en-US/docs/Web/CSS/background-image">background-image</a></code>, <code><a href="/en-US/docs/Web/CSS/border-image-source">border-image</a></code>, <code><a href="/en-US/docs/Web/CSS/mask-image">mask-image</a></code>, etc.</p> + +<p>Um programmatisch ein Bild zu erstellen, das von einem CSS stylesheet verwendet wird, müssen wir folgende Schritte abarbeiten:</p> + +<ol> + <li>Lege ein "paint worklet" mit der <code><a href="/en-US/docs/Web/API/PaintWorklet/registerPaint">registerPaint()</a></code> Funktion fest.</li> + <li>Melde das worklet an.</li> + <li>Binde mit Include die <code>{{cssxref('paint()','paint()')}}</code> CSS Funktion ein.</li> +</ol> + +<p>Zum besseren Verständnis dieser einzelnen Schritte werden wir eine halbhohe farbliche Markierung wie in folgender Titelzeile erstellen:</p> + +<p><img alt="Text reading 'My Cool Header' with a solid yellow background image block on the bottom left two thirds of the header" src="https://mdn.mozillademos.org/files/16774/mycoolheader.png" style="height: 54px; width: 239px;"></p> + +<h2 id="CSS_paint_worklet">CSS paint worklet</h2> + +<p>In einer externen Skript-Datei nutzen wir die <code><a href="/en-US/docs/Web/API/PaintWorklet/registerPaint">registerPaint()</a></code> Funktion, um unser <a href="/en-US/docs/Web/API/PaintWorklet">CSS Paint worklet</a> zu benennen. Diese benötigt zwei Parameter. Der erste ist der Name, den wir dem worklet geben — diesen Namen werden wir als einen Parameter von der paint() Funktion verwenden, wenn wir das Bild einem Element hinzufügen wollen. Der zweite Parameter ist die Klasse, die die ganze Magie ausführt: die die Kontext-Entscheidungen festlegt und natürlich das Bild, das wir auf unsere Oberfläche malen wollen.</p> + +<pre class="brush: js notranslate">registerPaint('headerHighlight', class { + + /* + definiere dies, wenn die Alphatransparenz erlaubt ist; + alpha ist standardmäßig true; wenn auf false gesetzt, sind + alle Farben, die auf der Canvas genutzt werden, opak + */ + static get contextOptions() { + return { alpha: true }; + } + + /* + <strong>ctx</strong> ist der 2D Zeichen Kontext + eine Untermenge der <a href="/en-US/docs/Web/API/Canvas_API">HTML5 Canvas API</a>. + */ + paint(ctx) { + ctx.fillStyle = 'hsla(55, 90%, 60%, 1.0)'; + ctx.fillRect(0, 15, 200, 20); /* order: x, y, w, h */ + } +});</pre> + +<p>In diesem Klassenbeispiel haben wir die Umstände (options) eines einzelnen Kontexts mit der <code>contextOptions()</code> Funktion festgelegt: wir haben ein einfaches Objekt zurückgegeben, das aussagt, dass die Alphatransparenz erlaubt ist.</p> + +<p>Wir haben dann die <code>paint()</code> Funktion verwendet, um unser Objekt auf die Canvas zu zeichnen.</p> + +<p>Die <code>paint()</code> Funktion kann drei Parameter aufnehmen. Hier übergeben wir nur ein Argument: den Rendering Kontext (wir schauen uns das im weiteren Verlauf noch genauer an), der oftmals mit dem Variablennamen <code>ctx</code> bezeichnet wird. Der 2D Rendering Context ist eine Untermenge der <a href="/en-US/docs/Web/API/Canvas_API">HTML5 Canvas API</a>; die Version, die für CSS Houdini verfügbar is (auch <code>PaintRenderingContext2D genannt</code>), ist eine weitere Untermenge, die über die meisten Zusätze verfügt, die auch in der Canvas API vorhanden sind, mit Ausnahme von <code>CanvasImageData</code>, <code>CanvasUserInterface</code>, <code>CanvasText</code>, und <code>CanvasTextDrawingStyles</code> APIs.</p> + +<p>Wir weisen mit <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> den Wert <code>hsla(55, 90%, 60%, 1.0)</code> zu, ein blasses Gelb, und rufen dann <code>fillRect()</code> auf, um ein farbiges Rechteck zu erstellen. Die Parameter von <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillRect">fillRect()</a></code> sind, in der Abfolge, x-Achse und y-Achse (und zugleich die feste Koordinate), Breite und Höhe. <code>fillRect(0, 15, 200, 20)</code> erstellt ein Rechteck von 200 Einheiten Breite und 20 Einheiten Höhe, die 0 Einheiten von der linken und 15 Einheiten von der oberen Seite der Box entfernt sind, in der das Rechteck eingezeichnet wird.</p> + +<p>Wir können die CSS <code><a href="/en-US/docs/Web/CSS/background-size">background-size</a></code> and <code><a href="/en-US/docs/Web/CSS/background-position">background-position</a></code> Eigenschaften (properties) verwenden, um das Hintergrundbild in seiner Größe und Position zu verändern, aber die oben festgelegten Werte sind die Standardwerte der gelben Box, die wir in unserem paint worklet definiert haben.</p> + +<p>Wir haben dieses Beispiel einfach gehalten. Für mehr Möglichkeiten werfen Sie bitte einen Blick in die <a href="/en-US/docs/Web/HTML/Element/canvas">Canvas Dokumentation</a>. Wir werden weiter unten im Tutorial auch komplexere Beispiele nutzen.</p> + +<h2 id="Das_paint_worklet_verwenden">Das paint worklet verwenden</h2> + +<p>Um das paint worklet zu verwenden, müssen wir dies mit <code><a href="/en-US/docs/Web/API/Worklet/addModule">addModule()</a></code> anmelden und in unsere CSS einfügen, wobei wir sicherstellen müssen, dass der CSS Selektor zu einem DOM Knoten in unserem HTML-Code passt.</p> + +<h3 id="Das_worklet_anmelden">Das worklet anmelden</h3> + +<p>Wir haben unser paint worklet in einer externen script-Datei erstellt, wie oben geziegt. Wir müssen jetzt unser <a href="/en-US/docs/Web/API/PaintWorklet">worklet</a> in unserer Hauptanwendung anmelden:</p> + +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('nameOfPaintWorkletFile.js');</pre> + +<p>Dazu benutzen wir die von Paint Worklet bereitgestellte Funktion <code>addModule()</code> in einem <code><script></code>-Block innerhalb unseres HTML oder in einer externen JavaScript-Datei, die dann seinerseits von der Hauptanwendung aufgerufen werden muss.</p> + +<p>In unserem Beispiel ist das worklet auf GitHub gespeichert.</p> + +<div id="paintapi"> +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/01partOne/header-highlight.js');</pre> + +<h3 id="Auf_das_paint_worklet_in_CSS_verweisen">Auf das paint worklet in CSS verweisen</h3> + +<p>Haben wir das paint worklet angemeldet, können wir es in CSS benutzen. Dabei kann man die Funktion <code>paint()</code> so benutzen, wie man auch jeden anderen <code><image></code> Typ verwendet. In <code>paint()</code> wird als Parameter derselbe Name des worklets übergeben, den wir bei <code>registerPaint()</code> eingetragen haben.</p> + +<pre class="brush: css notranslate">.fancy { + background-image: paint(headerHighlight); +}</pre> + +<h3 id="Alles_zusammensetzen">Alles zusammensetzen</h3> + +<p>Nun können wir die fancy-Klasse aus CSS einem HTML-Element ganz normal in der Property class übergeben, um die gelbe Box als Hintergrundbild erscheinen zu lassen:</p> + +<pre class="brush: html notranslate"><h1 class="fancy">My Cool Header</h1></pre> + +<p>Das folgende Beispiel wird wie das obige Beispiel in einem <a href="/Web/API/CSS/paintWorklet#Browser_compatibility">Browsers, der die CSS Painting API unterstützt</a>, aussehen.</p> +</div> + +<p>{{EmbedLiveSample("paintapi", 120, 120)}}</p> + +<p>Während Sie vom HTML aus das worklet nicht mehr (innerlich) verändern können, können Sie trotzdem mit CSS über <code>background-size</code> und <code>background-position</code> Größe und Position des Bildes anpassen.</p> + +<h2 id="PaintSize">PaintSize</h2> + +<p>Im Beispiel oben haben wir eine Box aus 20x200 Einheiten erstellt, die 15 Einheiten vom oberen Rand der umgebenen Box - eines HTML-Elements - entfernt liegt, gleichgültig, welche Größe die umhüllende Box selbst hat. Ist der Text klein, sieht die Box wie eine große Unterstreichung aus, ist er groß und lang, ist die Box gleich einem Balken unter den ersten Buchstaben. Günstiger wäre aber, wenn das Hintergrundbild relativ zur Größe des umhüllenden Elementes wäre. Dafür können wir die <code>paintSize</code> Property, bzw. <code>size.width</code> und <code>size.height</code>, verwenden. Diese übernimmt die Breite und Höhe des umliegenden Elements und rechnet die Größe des worklets dafür aus.</p> + +<p><img alt="The background is 50% of the height and 60% of the width of the element" src="https://mdn.mozillademos.org/files/16783/mycoolheadersized.png" style="height: 148px; width: 554px;"></p> + +<p>In diesem Beispiel-Bild ist der Hintergrund proportional zu der Größe des umhüllenden Elements. Das dritte Beispiel hat als Breite <code>width: 50%</code>; das Hintergrundbild passt sich in den ersten beiden Beispielen der Größe der Schrift an und damit der Höhe des Blocks, im dritten Beispiel sieht man aber auch deutlich, dass die Breite ebenfalls passend gemacht wird.</p> + +<p>Der Code, mit dem das möglich ist, sieht dann folgendermaßen aus:</p> + +<pre class="brush: js notranslate">registerPaint('headerHighlight', class { + + static get contextOptions() { + return { alpha: true }; + } + + /* + <strong>ctx</strong> is the 2D drawing context + <strong>size</strong> is the paintSize, the dimensions (height and width) of the box being painted + */ + + paint(ctx, size) { + ctx.fillStyle = 'hsla(55, 90%, 60%, 1.0)'; + ctx.fillRect( 0, size.height / 3, size.width * 0.4, size.height * 0.6 ); + } +});</pre> + +<p>Der Code unterscheidet sich an zwei Stellen vom ersten Beispiel:</p> + +<ol> + <li>Wir haben ein zweites Argument in <code>paint()</code> eingefügt, die Größe <code>size</code>.</li> + <li>Wir berechnen die Dimensionen und die Position unseres Rechtecks relativ zu dieser Größe <code>size</code> und nicht mehr mit absoluten Werten, mit Hilfe der Properties <code>.width</code> und <code>.height</code>.</li> +</ol> + +<p>Unsere HTML-Elemente haben nur ein Hintergrundbild, welches sich in Größe und Breite ändert.</p> + +<div class="hidden" id="example2"> +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/02partTwo/header-highlight.js');</pre> + +<pre class="brush: css notranslate">.fancy { + background-image: paint(headerHighlight); +} +.half { + width: 50%; +}</pre> + +<pre class="brush: html notranslate"><h1 class="fancy">Largest Header</h1> +<h6 class="fancy">Smallest Header</h6> +<h3 class="fancy half">50% width header</h3> +</pre> +</div> + +<p>Wenn du mit diesem worklet herumspielst, kannst du dessen Größe über die Eigenschaften <code>font-size</code> und <code>width</code> des umhüllenden Elements ändern.</p> + +<p>In Browsern, die CSS Paint API unterstützen, erscheint das unten aufgeführte Beispielt wie das Bild oben.</p> + +<p>{{EmbedLiveSample("example2", 300, 300)}}</p> + +<h2 id="Properties_anpassen">Properties anpassen</h2> + +<p>Zusätzlich zu der Größe des Elements kann ein worklet auch auf andere CSS-Eigenschaften zugreifen.</p> + +<pre class="brush: js notranslate">registerPaint('cssPaintFunctionName', class { + static get inputProperties() { return ['PropertyName1', '--customPropertyName2']; } + static get inputArguments() { return ['<color>']; } + static get contextOptions() { return {alpha: true}; } + + paint(drawingContext, elementSize, styleMap) { + // Paint code goes here. + } +}); +</pre> + +<p>Die drei Parameter der Funktion <code>paint()</code> enthalten den Zeichenkontext, die Größe des Malgrundes (meist des umgebenden Elements) und Eigenschaften (properties). Um auf die Eigenschaften zugreifen zu können, muss man die statische Methode <code>inputProperties()</code> aufrufen, die den Zugriff auf die CSS properties ermöglicht, sowohl der regulären als auch <a href="/en-US/docs/Web/CSS/CSS_Variables">angepasster Eigenschaften</a>. Diese liefert ein <code><a href="/en-US/docs/Glossary/array">array</a></code> mit den Namen der Eigenschaften zurück (wir werfen im letzten Abschnitt einen näheren Blick auf <code>inputArguments).</code></p> + +<h3 id="Example">Example</h3> + +<div id="example3"> +<p>Legen wir dazu eine Liste an, deren Hintergrundbild zwischen drei verschiedenen Farben und drei unterschiedlichen Breiten wechselt.</p> + +<p><img alt="The width and color of the background image changes based on the custom properties" src="https://mdn.mozillademos.org/files/16784/boxbg.png" style="height: 255px; width: 739px;"></p> + +<p>In unserer CSS weisen wir verschiedene Farben und eine Anpassung der Breite des worklets über die <code>--boxColor</code> und <code>--widthSubtractor</code> Eigenschaften zu.</p> + +<pre class="brush: html; hidden notranslate"><ul> + <li>item 1</li> + <li>item 2</li> + <li>item 3</li> + <li>item 4</li> + <li>item 5</li> + <li>item 6</li> + <li>item 7</li> + <li>item 8</li> + <li>item 9</li> + <li>item 10</li> + <li>item 11</li> + <li>item 12</li> + <li>item 13</li> + <li>item 14</li> + <li>item 15</li> + <li>item 16</li> + <li>item 17</li> + <li>item</li> +</ul> +</pre> + +<pre class="brush: js; hidden notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/worklets/boxbg.js');</pre> + +<pre class="brush: css notranslate">li { + background-image: paint(boxbg); + --boxColor: hsla(55, 90%, 60%, 1.0); +} + +li:nth-of-type(3n) { + --boxColor: hsla(155, 90%, 60%, 1.0); + --widthSubtractor: 20; +} + +li:nth-of-type(3n+1) { + --boxColor: hsla(255, 90%, 60%, 1.0); + --widthSubtractor: 40; +}</pre> +</div> + +<p>Beachte, dass wir im CSS Eigenschaften verwenden, die nicht zum normalen CSS gehören, sondern von uns selbst definiert worden sind: <code>boxColor</code> und <code>widthSubtractor</code>. Auf diese können wir im worklet zugreifen, wenn wir diese über <code>inputProperties()</code> zugänglich machen.</p> + +<pre class="brush: js notranslate">registerPaint('boxbg', class { + + static get contextOptions() { return {alpha: true}; } + + /* + use this function to retrieve any custom properties (or regular properties, such as 'height') + defined for the element, return them in the specified array + */ + <strong>static get inputProperties() { return ['--boxColor', '--widthSubtractor']; }</strong> + + paint(ctx, size, props) { + /* + ctx -> drawing context + size -> paintSize: width and height + props -> properties: get() method + */ + + ctx.fillStyle = <strong>props.get('--boxColor')</strong>; + ctx.fillRect(0, size.height/3, size.width*0.4 - <strong>props.get('--widthSubtractor')</strong>, size.height*0.6); + } +});</pre> + +<p>Wir haben die Methode <code>inputProperties()</code> in der <code>registerPaint()</code> Klasse verwendet, um die Werte der beiden von uns definierten Eigenschaften zu erhalten, die das worklet <code>boxbg</code> anwenden. Mit <code>inputProperties()</code> legen wir uns einen Array an, der normale CSS-Eigenschaften wie auch selbst definierte erhalten kann.</p> + +<p>In unserem <code><script></code>-Block melden wir das worklet an:</p> + +<div id="paintapi"> +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/worklet/boxbg.js');</pre> +</div> + +<p>{{EmbedLiveSample("example3", 300, 300)}}</p> + +<p>In der Anwendung können wir zwar nicht das Script des worklets verändern, aber alle Werte, die über CSS übergeben werden und die vom worklet verarbeitet werden.</p> + +<h2 id="Komplexität_hinzufügen">Komplexität hinzufügen</h2> + +<p>Das obenstehende Beispiel ist nicht sonderlich aufregend, da man es ebenso mit CSS in wenigen Schritten und ohne den Aufwand eines worklets programmieren kann, etwa, indem man <a href="/en-US/docs/Learn/CSS/Howto/Generated_content">dekorative Inhalte</a> mit <code><a href="/en-US/docs/Web/CSS/::before">::before</a> hinzufügt</code> oder mit <code>background: linear-gradient(yellow, yellow) 0 15px / 200px 20px no-repeat;</code> - Was die CSS Painting API so interessant und machtvoll macht, ist die Möglichkeit, komplexe Bilder zu erstellen und Variablen zu übergeben.</p> + +<p>Werfen wir einen Blick auf ein komplexeres Beispiel.</p> + +<pre class="brush: js notranslate">registerPaint('headerHighlight', class { + static get inputProperties() { return ['--highColour']; } + static get contextOptions() { return {alpha: true}; } + + paint(ctx, size, props) { + + /* set where to start the highlight & dimensions */ + const x = 0; + const y = size.height * 0.3; + const blockWidth = size.width * 0.33; + const highlightHeight = size.height * 0.85; + const color = props.get('--highColour'); + + ctx.fillStyle = color; + + ctx.beginPath(); + ctx.moveTo( x, y ); + ctx.lineTo( blockWidth, y ); + ctx.lineTo( blockWidth + highlightHeight, highlightHeight ); + ctx.lineTo( x, highlightHeight ); + ctx.lineTo( x, y ); + ctx.closePath(); + ctx.fill(); + + /* create the dashes */ + for (let i = 0; i < 4; i++) { + let start = i * 2; + ctx.beginPath(); + ctx.moveTo( (blockWidth) + (start * 10) + 10, y ); + ctx.lineTo( (blockWidth) + (start * 10) + 20, y ); + ctx.lineTo( (blockWidth) + (start * 10) + 20 + (highlightHeight), highlightHeight ); + ctx.lineTo( (blockWidth) + (start * 10) + 10 + (highlightHeight), highlightHeight ); + ctx.lineTo( (blockWidth) + (start * 10) + 10, y ); + ctx.closePath(); + ctx.fill(); + } + } // paint +});</pre> + +<div id="example4"> +<p>Wir können dann einige Zeilen HTML mit der entsprechenden Klasse aus CSS schreiben:</p> + +<pre class="brush: html notranslate"><h1 class="fancy">Largest Header</h1> +<h3 class="fancy">Medium size header</h3> +<h6 class="fancy">Smallest Header</h6></pre> + +<p>Dann geben wir den einzelnen HTML-Elementen je einen verschiedenen Wert für die <a href="/en-US/docs/Web/CSS/CSS_Variables">von uns definierte Eigenschaft</a> <code>--highColour:</code></p> + +<pre class="brush: css notranslate">.fancy { + background-image: paint(headerHighlight); +} +h1 { --highColour: hsla(155, 90%, 60%, 0.7); } +h3 { --highColour: hsla(255, 90%, 60%, 0.5); } +h6 { --highColour: hsla(355, 90%, 60%, 0.3); }</pre> + +<p>Und wir melden das worklet an:</p> + +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/03partThree/header-highlight.js');</pre> + +<p>{{EmbedLiveSample("example4", 300, 300)}}</p> + +<p>Während man das worklet selbst nicht ändern kann, kann man mit CSS und HTML jedoch herumspielen. Vielleicht probieren Sie mal <code><a href="/en-US/docs/Web/CSS/float">float</a></code> und <code><a href="/en-US/docs/Web/CSS/clear">clear</a></code> bei den Titelzeilen <code><h1></code>, <code><h3></code> und <code><h6></code> aus.</p> + +<p>Man kann natürlich auch Hintergrundbilder ohne CSS paint API erstellen. Das kann allerdings zu einem großen Mehraufwand und wesentlich mehr Code führen. Mit CSS Paint API kann ein worklet immer wieder verwendet werden und über eine Parameter-Übergabe rasch angepasst werden.</p> +</div> + +<h2 id="Parameter_übergeben">Parameter übergeben</h2> + +<p>Mit der CSS Paint API können wir nicht nur auf selbstdefinierte Eigenschaften zugreifen, sondern auch über die CSS-Funktion <code>paint()</code> auch Parameter übergeben.</p> + +<p>Nehmen wir an, wir wollen ab und zu den Hintergrund nur mit einem Strich statt vollständig füllen. Dafür können wir ein Extra-Argument übergeben, welches dann im worklet abgefragt und entsprechend verarbeitet wird.</p> + +<pre class="brush: css notranslate">li { + background-image: paint(hollowHighlights, stroke); +} +</pre> + +<p>Mit der Methode <code>inputArguments()</code> in der Klasse <code>registerPaint()</code> machen wir das zusätzliche Argument aus der CSS-Funktion <code>paint()</code> zugänglich:</p> + +<pre class="brush: js notranslate">static get inputArguments() { return ['*']; } +</pre> + +<p>Und wenn wir darauf zugreifen wollen:</p> + +<pre class="brush:js notranslate">paint(ctx, size, props, args) { + + // use our custom arguments + const hasStroke = args[0].toString(); + + // if stroke arg is 'stroke', don't fill + if (hasStroke === 'stroke') { + ctx.fillStyle = 'transparent'; + ctx.strokeStyle = colour; + } + ... +} +</pre> + +<p>Wir können auch mehr als ein Argument übergeben:</p> + +<pre class="brush: css notranslate">li { + background-image: paint(hollowHighlights, stroke, 10px); +} +</pre> + +<p>Wir können auch den Datentyp genau angeben. Wenn wir die Werte der Argumente mit <code>get</code> holen, fragen wir dann speziell nach einer <code><length></code> Einheit.</p> + +<pre class="brush: js notranslate">static get inputArguments() { return ['*', '<length>']; }</pre> + +<p>In diesem Fall haben wir spezifisch nach einem <code><length></code> Attribut gefragt. Das erste Element des Arrays wird dann als <code><a href="/en-US/docs/Web/API/CSSUnparsedValue">CSSUnparsedValue</a></code>, das zweite als <code><a href="/en-US/docs/Web/API/CSSStyleValue">CSSStyleValue</a></code> übergeben.</p> + +<p>Wenn das selbstdefinierte Argument ein CSS-Wert ist, zum Beispiel eine Maßeinheit, können wir die Typed OM CSSStyleValue Klasse (und deren Unterklassen) aufrufen, indem wir das Schlüsselwort für diesen Typen in der Methode <code>inputArguments()</code> nutzen.</p> + +<p>Fügen wir einfach ein weiteres Argument für die Pixel-Breite unserer Hintergrundlinie hinzu:</p> + +<pre class="brush: css notranslate">li { + background-image: paint(hollowHighlights, stroke, 10px); +} +</pre> + +<p>Wenn wir mit <code>get</code> unsere Argumentenliste holen, können wir direkt nach der <code><length></code> Einheit fragen.</p> + +<pre class="brush: js notranslate">static get inputArguments() { return ['*', '<length>']; } +</pre> + +<p>Nun können wir Typen und Werte der Properties übergeben, was bedeutet: wir können die Anzahl der Pixel und den Typ Nummer direkt verwenden (zugegeben nimmt <code>ctx.lineWidth</code> einen Float als Wert und eigentlich keinen Wert mit Längeneinheiten, aber um des Beispiels willen ...).</p> + +<pre class="brush: js notranslate">paint(ctx, size, props, args) { + + const strokeWidth = args[1]; + + if (strokeWidth.unit === 'px') { + ctx.lineWidth = strokeWidth.value; + } else { + ctx.lineWidth = 1.0; + } + + ... +} +</pre> + +<p>Es ist wichtig, hier den Unterschied zwischen selbsterstellten Properties und den Argumenten zu erwähnen. Selbsterstellte Properties (und auch alle Properties für einen bestimmten Selektor) sind global - sie können überall in unserem CSS und JS verwendet werden.</p> + +<p>Wenn Sie zum Beispiel ein <code>--mainColor</code> definiert haben, der dazu dient, eine Farbe mit der Funktion <code>paint()</code> zu setzen, kann dieser auch dazu verwendet werden, anderswo im CSS Farben zu setzen. Wenn Sie diesen Wert speziell für paint ändern wollen, kann sich das als schwierig erweisen. Hier kommt dann das angepasste Argument ins Spiel. Argumente dienen dazu, das zu kontrollieren, was man aktuell zeichnet, während Properties dazu dienen, den Stil zu kontrollieren.</p> + +<p><img alt="The list items have a background image that is either pink, purple or green, with different stroke widths, and the green one being filled." src="https://mdn.mozillademos.org/files/16786/hollowfilled.png" style="height: 292px; width: 327px;"></p> + +<p>Nun können wir die Vorteile dieser API sehen: wir können zahlreiche selbsterstellte Properties und Argumente dafür verwenden, um wiederverwendbare und vollkommen kontrollierbare Styling-Funktionen zu erstellen.</p> + +<pre class="brush: js notranslate">registerPaint('hollowHighlights', class { + + static get inputProperties() { return ['--boxColor']; } + // Input arguments that can be passed to the `paint` function + static get inputArguments() { return ['*','']; } + + static get contextOptions() { return {alpha: true}; } + + paint(ctx, size, props, args) { + // ctx -> drawing context + // size -> size of the box being painted + // props -> list of custom properties available to the element + // args -> list of arguments set when calling the paint() function in the css + + // where to start the highlight & dimensions + const x = 0; + const y = size.height * 0.3; + const blockWidth = size.width * 0.33; + const blockHeight = size.height * 0.85; + + // the values passed in the paint() function in the CSS + const colour = props.get( '--boxColor' ); + const strokeType = args[0].toString(); + const strokeWidth = parseInt(args[1]); + + + // set the stroke width + if ( strokeWidth ) { + ctx.lineWidth = strokeWidth; + } else { + ctx.lineWidth = 1.0; + } + // set the fill type + if ( strokeType === 'stroke' ) { + ctx.fillStyle = 'transparent'; + ctx.strokeStyle = colour; + } else if ( strokeType === 'filled' ) { + ctx.fillStyle = colour; + ctx.strokeStyle = colour; + } else { + ctx.fillStyle = 'none'; + ctx.strokeStyle = 'none'; + } + + // block + ctx.beginPath(); + ctx.moveTo( x, y ); + ctx.lineTo( blockWidth, y ); + ctx.lineTo( blockWidth + blockHeight, blockHeight ); + ctx.lineTo( x, blockHeight ); + ctx.lineTo( x, y ); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + // dashes + for (let i = 0; i < 4; i++) { + let start = i * 2; + ctx.beginPath(); + ctx.moveTo( blockWidth + (start * 10) + 10, y); + ctx.lineTo( blockWidth + (start * 10) + 20, y); + ctx.lineTo( blockWidth + (start * 10) + 20 + blockHeight, blockHeight); + ctx.lineTo( blockWidth + (start * 10) + 10 + blockHeight, blockHeight); + ctx.lineTo( blockWidth + (start * 10) + 10, y); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + } + + } // paint +}); +</pre> + +<p>Wir können verschiedene Farbe und Strichstärken setzen und entscheiden, ob das Hintergrundbild gefüllt oder leer ist:</p> + +<div id="example5"> +<pre class="brush: css notranslate">li { + --boxColor: hsla(155, 90%, 60%, 0.5); + background-image: paint(hollowHighlights, stroke, 5px); +} + +li:nth-of-type(3n) { + --boxColor: hsla(255, 90%, 60%, 0.5); + background-image: paint(hollowHighlights, filled, 3px); +} + +li:nth-of-type(3n+1) { + --boxColor: hsla(355, 90%, 60%, 0.5); + background-image: paint(hollowHighlights, stroke, 1px); +}</pre> + +<pre class="brush: html; hidden notranslate"><ul> + <li>item 1</li> + <li>item 2</li> + <li>item 3</li> + <li>item 4</li> + <li>item 5</li> + <li>item 6</li> + <li>item 7</li> + <li>item 8</li> + <li>item 9</li> + <li>item 10</li> + <li>item 11</li> + <li>item 12</li> + <li>item 13</li> + <li>item 14</li> + <li>item 15</li> + <li>item 16</li> + <li>item 17</li> + <li>item</li> +</ul> +</pre> + +<p>In unserem <code><script></code>-Block melden wir das Worklet an:</p> + +<pre class="brush: js notranslate">CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/worklets/hollow.js');</pre> +</div> + +<p>{{EmbedLiveSample("example5", 300, 300)}}</p> + +<h2 id="Siehe_auch">Siehe auch</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/CSS_Painting_API">CSS Painting API </a></li> + <li><a href="/en-US/docs/Web/Houdini/CSS_Typed_OM">CSS Typed Object Model API</a></li> +</ul> diff --git a/files/de/web/api/css_painting_api/index.html b/files/de/web/api/css_painting_api/index.html new file mode 100644 index 0000000000..799979f66b --- /dev/null +++ b/files/de/web/api/css_painting_api/index.html @@ -0,0 +1,199 @@ +--- +title: CSS Painting API +slug: Web/API/CSS_Painting_API +tags: + - API + - CSS + - CSS Paint API + - Houdini + - NeedsTranslation + - Painting + - Reference + - TopicStub +translation_of: Web/API/CSS_Painting_API +--- +<div>{{DefaultAPISidebar("CSS Painting API")}}</div> + +<p>The CSS Painting API — part of the <a href="/en-US/docs/Web/Houdini">CSS Houdini</a> umbrella of APIs — allows developers to write JavaScript functions that can draw directly into an element's background, border, or content.</p> + +<h2 id="Concepts_and_usage">Concepts and usage</h2> + +<p>Essentially, the CSS Painting API contains functionality allowing developers to create custom values for {{cssxref('paint', 'paint()')}}, a CSS <code><a href="/en-US/docs/Web/CSS/image"><image></a></code> function. You can then apply these values to properties like {{cssxref("background-image")}} to set complex custom backgrounds on an element.</p> + +<p>For example:</p> + +<pre class="brush: css notranslate">aside { + background-image: paint(myPaintedImage); +}</pre> + +<p>The API defines {{domxref('PaintWorklet')}}, a {{domxref('worklet')}} that can be used to programmatically generate an image that responds to computed style changes. To find out more about how this is used, consult <a href="/en-US/docs/Web/API/CSS_Painting_API/Guide">Using the CSS Painting API</a>.</p> + +<h2 id="Interfaces">Interfaces</h2> + +<dl> + <dt>{{domxref('PaintWorklet')}}</dt> + <dd>Programmatically generates an image where a CSS property expects a file. Access this interface through <a href="https://developer.mozilla.org/en-US/docs/Web/API/CSS/paintWorklet" title="paintWorklet is a static, read-only property of the CSS interface that provides access to the PaintWorklet, which programmatically generates an image where a CSS property expects a file. "><code>CSS.paintWorklet</code></a>.</dd> + <dt>{{domxref('PaintWorkletGlobalScope')}}</dt> + <dd>The global execution context of the <code>paintWorklet</code>.</dd> + <dt>{{domxref('PaintRenderingContext2D')}}</dt> + <dd> + <p>Implements a subset of the <a href="/en-US/docs/Web/API/CanvasRenderingContext2D">CanvasRenderingContext2D API</a>. It has an output bitmap that is the size of the object it is rendering to.</p> + </dd> + <dt>{{domxref('PaintSize')}}</dt> + <dd>Returns the read-only values of the output bitmap's width and height.</dd> +</dl> + +<h2 id="Dictionaries">Dictionaries</h2> + +<dl> + <dt>{{domxref('PaintRenderingContext2DSettings')}}</dt> + <dd>A dictionary providing a subset of <a href="/en-US/docs/Web/API/CanvasRenderingContext2D">CanvasRenderingContext2D</a> settings.</dd> +</dl> + +<h2 id="Examples" name="Examples">Examples</h2> + +<p>To draw directly into an element's background using JavaScript in our CSS, we define a paint worklet using the <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/PaintWorklet/registerPaint">registerPaint()</a></code> function, tell the document to include the worklet using the paintWorklet addModule() method, then include the image we created using the CSS <code><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/paint()" title="The documentation about this has not yet been written; please consider contributing!"><code>paint()</code></a></code> function.</p> + +<p>We create our PaintWorklet called 'hollowHighlights' using the <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/PaintWorklet/registerPaint">registerPaint()</a></code> function:</p> + +<pre class="brush: js notranslate">registerPaint('hollowHighlights', class { + + static get inputProperties() { return ['--boxColor']; } + + static get inputArguments() { return ['*','<length>']; } + + static get contextOptions() { return {alpha: true}; } + + paint(ctx, size, props, args) { + const x = 0; + const y = size.height * 0.3; + const blockWidth = size.width * 0.33; + const blockHeight = size.height * 0.85; + + const theColor = props.get( '--boxColor' ); + const strokeType = args[0].toString(); + const strokeWidth = parseInt(args[1]); + + console.log(theColor); + + if ( strokeWidth ) { + ctx.lineWidth = strokeWidth; + } else { + ctx.lineWidth = 1.0; + } + + if ( strokeType === 'stroke' ) { + ctx.fillStyle = 'transparent'; + ctx.strokeStyle = theColor; + } else if ( strokeType === 'filled' ) { + ctx.fillStyle = theColor; + ctx.strokeStyle = theColor; + } else { + ctx.fillStyle = 'none'; + ctx.strokeStyle = 'none'; + } + + + ctx.beginPath(); + ctx.moveTo( x, y ); + ctx.lineTo( blockWidth, y ); + ctx.lineTo( blockWidth + blockHeight, blockHeight ); + ctx.lineTo( x, blockHeight ); + ctx.lineTo( x, y ); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + + for (let i = 0; i < 4; i++) { + let start = i * 2; + ctx.beginPath(); + ctx.moveTo( blockWidth + (start * 10) + 10, y); + ctx.lineTo( blockWidth + (start * 10) + 20, y); + ctx.lineTo( blockWidth + (start * 10) + 20 + blockHeight, blockHeight); + ctx.lineTo( blockWidth + (start * 10) + 10 + blockHeight, blockHeight); + ctx.lineTo( blockWidth + (start * 10) + 10, y); + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + } + } +});</pre> + +<div id="hollowExample"> +<p>We then include the paintWorklet:</p> + +<pre class="brush: html hidden notranslate"><ul> + <li>item 1</li> + <li>item 2</li> + <li>item 3</li> + <li>item 4</li> + <li>item 5</li> + <li>item 6</li> + <li>item 7</li> + <li>item 8</li> + <li>item 9</li> + <li>item 10</li> + <li>item 11</li> + <li>item 12</li> + <li>item 13</li> + <li>item 14</li> + <li>item 15</li> + <li>item 16</li> + <li>item 17</li> + <li>item 18</li> + <li>item 19</li> + <li>item 20</li> +</ul></pre> + +<pre class="brush: js notranslate"> CSS.paintWorklet.addModule('https://mdn.github.io/houdini-examples/cssPaint/intro/worklets/hilite.js'); +</pre> + +<p>Then we can use the {{cssxref('<image>')}} with the CSS {{cssxref('paint()')}} function:</p> + +<pre class="brush: css notranslate">li { + --boxColor: hsla(55, 90%, 60%, 1.0); + background-image: paint(hollowHighlights, stroke, 2px); +} + +li:nth-of-type(3n) { + --boxColor: hsla(155, 90%, 60%, 1.0); + background-image: paint(hollowHighlights, filled, 3px); +} + +li:nth-of-type(3n+1) { + --boxColor: hsla(255, 90%, 60%, 1.0); + background-image: paint(hollowHighlights, stroke, 1px); +}</pre> +</div> +<p>We've included a custom property in the selector block defining a boxColor. Custom properties are accessible to the PaintWorklet.</p> + +<p>{{EmbedLiveSample("hollowExample", 300, 300)}}</p> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('CSS Painting API')}}</td> + <td>{{Spec2('CSS Painting API')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<p>See the browser compatibility data for each CSS Painting API Interfaces.</p> + +<h2 id="See_Also">See Also</h2> + +<ul> + <li><a href="/en-US/docs/Web/Houdini/Learn/CSS_Painting_API">Using the CSS Painting API</a></li> + <li><a href="/en-US/docs/Web/CSS_Typed_OM">CSS Typed Object Model API</a></li> + <li><a href="/en-US/docs/Web/Houdini">CSS Houdini</a></li> +</ul> |