Benutzer:Rolf b/Filter in SVG/Das Filter-Element

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Wenn die vordefinierten Filter nicht ausreichen, gibt es die Möglichkeit, eigene Filter aus einem Satz von vordefinierten Filtereffekten (Ur-Filter oder Filter-Primitive) zusammenzusetzen. Dies geschieht mit Hilfe des SVG-Elements <filter>.

Definition

Ein einfaches Beispiel ist ein Weichzeichner. Schauen wir uns an, wie das aussieht:

Unschärfefilter als filter-Element
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 150" width="300" height="150">
  <defs>
    <filter id="soft-3">
      <feGaussianBlur stdDeviation="2" />
    </filter>
  </defs>

  <rect x="10" y="10" width="130" height="100"
        fill="red" stroke="black" stroke-width="5" />
  <rect x="160" y="10" width="130" height="100" filter="url(#soft-3)"
        fill="red" stroke="black" stroke-width="5" />
</svg>
SVG-Filter-Demo1.svg

Die Kindelemente des <filter>-Elements sind die Filtereffekte. Alle Filtereffekte haben einen Tagnamen, der mit fe beginnt – aber Vorsicht, nicht alles, was mit fe beginnt, ist auch ein Filtereffekt.

Unser Beispiel verwendet den Filtereffekt feGaussianBlur, das ist ein Unschärfefilter, der auf der von Carl Friedrich Gauß entwickelten Normalverteilungskurve basiert.[1] Diese Kurve ist eigentlich ein Werkzeug der Statistik, aber wegen ihrer Glockenform eignet sie sich gut, um einen Unschärfeübergang mathematisch zu beschreiben. Der Statistikbegriff „Standardabweichung“ ist ein Maß für die Breite der Glocke, und deshalb heißt das Filtereffekt-Attribut, das die Stärke der Unschärfe angibt, stdDeviation.

Einbindung

Das <filter>-Element im <defs>-Abschnitt hat das Attribut id="soft-3" bekommen. Mit dieser ID kann der Filter auf das <rect>-Element mittels filter="url(#soft-3)" angewendet werden. In SVG ist das Filter-Attribut der übliche Weg. In HTML weist man Filter per CSS über die Filter-Eigenschaft zu. Beide Methoden bieten die gleichen Möglichkeiten.

Ein Filter muss dabei nicht zwangsläufig im gleichen Dokument stehen. Wenn sich der Weichzeichner beispielsweise in filtersammlung.svg befindet, kann man ihn mit url(filtersammlung.svg#soft-3) einbinden.

Es ist auch möglich, mehrere Filter anzuwenden. Dazu notiert man die gewünschten Filter (eigene oder vordefinierte) nacheinander, durch Leerzeichen getrennt, im filter-Attribut oder der filter-Eigenschaft.

Verketten von Filtereffekten

Einzelne Filtereffekte können nützlich sein, wirklich mächtig werden Filter aber erst, wenn man mehrere verkettet. Um zu verstehen, wie das funktioniert, müssen wir einen genaueren Blick darauf werfen, wie Filter angewendet werden.

Wie bereits in der Einführung erwähnt, werden Filter auf die RGB-Bilddarstellung eines Elements angewendet und erzeugen ein neues Bild. In einem Filter mit mehreren Effekten ist es standardmäßig so, dass der erste Effekt auf das gefilterte Element angewendet wird, der zweite Effekt wird auf das Ergebnis des ersten Effekts angewendet, und so weiter. Das Ergebnis des letzten Effekts ist dann das, was der Browser auf den Bildschirm zeichnet.

Dieser lineare Zusammenhang lässt sich aufbrechen. Dazu dienen die Attribute in und result der Filtereffekte. Mit dem result-Attribut lässt sich ein Effektergebnis benennen, und mit dem in-Attribut (bei einigen Effekten kommt ein in2-Attribut hinzu) kann man angeben, was die Eingabe für diesen Effekt sein soll. Darüber hinaus gibt es einige vordefinierte Namen, mit denen auf die RBG-Darstellung des ungefilterten Elements Bezug genommen werden kann. Davon sind nur zwei generell verwendbar:

SourceGraphic
Die normale RGB-Darstellung des Elements. Genauer gesagt: Es ist die RGBA-Darstellung, jeder Bildpunkt hat auch einen Alpha-Wert (Transparenz).
SourceAlpha
Wie SourceGraphic, aber in allen Bildpunkten sind Rot, Grün und Blau auf 0 gesetzt und nur der Alphawert wird übernommen. Man kann SourceAlpha verwenden, um überall dort, wo das gefilterte Element nicht transparent ist, die Darstellung zu modifizieren und den transparenten Teil unverändert zu lassen.

Die Filterspezfikation definiert darüber hinaus die Namen BackgroundImage, BackgroundAlpha, FillPaint und StrokePaint, deren Browserunterstützung aber schlecht ist:

  • Firefox: Kennt FillPaint und StrokePaint. Die beiden anderen werden wie SourceGraphic behandelt.
  • Chromium-Familie: Kennt nichts davon und behandelt sie wie unbekannte Namen.
  • Safari: Kennt ebenfalls nichts davon (tbc)
  • PaleMoon (um einen Exoten einzubeziehen): Kennt als Firefox-Abkömmling FillPaint und StrokePaint. Aber die beiden anderen werden wie unbekannte Namen behandelt, was im Unterschied zu Chromia und Firefox bedeutet, dass der Filter ein leeres Ergebnis erzeugt.

Ein komplexeres Beispiel

Das folgende Bild zeigt die Anwendung eines komplexeren Filters auf ein einfaches rotes Rechteck mit schwarzem Rand (mit „SourceGraphic“ beschriftet). Die übrigen Bildfelder sind mit dem Filtereffekt beschriftet, der sie erzeugt hat. Die Pfeile geben an, welches Bildfeld die Eingabe für diesen Filter war.

SVG-Filter-Demo2.svg

Das feGaussianBlur-Feld kennen wir schon - beinahe. Es ist hier schwarz, und das liegt daran, dass für den Filtereffekt nicht SourceGraphic, sondern SourceAlpha als Eingabe diente. Der Filtereffekt sieht so aus:

 <feGaussianBlur in="SourceAlpha" stdDeviation="2" result="blurred" />

Für das darunter befindliche Feld wird der Filtereffekt feOffset genutzt. Dieser Effekt verschiebt den Inhalt seines Eingangsbildes um einen bestimmten x- und y-Wert. Dabei geht ein Teil des Bildes verloren (es wird „hinausgeschoben“, und gegenüber wird Transparenz „hineingeschoben“. So sieht es aus:

 <feOffset in="blurred" dx="5" dy="5" result="shadowForm" />

Für den feOffset-Effekt haben wir in="blurred" angegeben, um klarzumachen, dass das Ergebnis des Blur-Effekts die Eingabe sein soll. Wenn beide Effekt direkt hintereinander stehen, kann man das in-Attribut – wie eingangs beschrieben – auch weglassen.

Als drittes gibt es ein einfaches grünes Feld. Es entsteht durch den feFlood-Effekt, der die vom Filtereffekt beeinflusste Region einfach mit einer bestimmten Farbe füllt. Auffällig ist hier, dass das grüne Feld größer ist als die Eingangsgrafik. Das liegt daran, dass die Filterregion standardmäßig in jeder Richtung 10% größer ist als das gefilterte Bild, damit genug Platz für die Ergebnisse von Blur- oder Offset-Effekten ist. Wir werden darauf noch näher eingehen. Der feFlood-Effekt sie so aus:

 <feFlood flood-color="green" result="allGreen" />

Ein in-Attribut fehlt und ist für feFlood auch nicht vorgesehen, weil dieser Filtereffekt nicht auf ein anderes Bild wirkt, sondern lediglich eine Farbfläche erzeugt.

Darunter folgt nun die Kombination von feOffset- und feFlood-Ergebnis. Dazu verwenden wir den feComposite-Effekt, der zwei Bilder miteinander kombiniert. Das operator-Attribut bezeichnet den Algorithmus, der dabei zu verwenden ist. Für diese Kombination haben wir operator="in" verwendet:

 <feComposite in="allGreen" operator="in" in2="shadowForm" result="greenShadow" />

Die Wirkung des Effekts ist genau so zu lesen, wie die Attribute aufgeschrieben sind: Erzeuge einen Ergebnisbildpunkt, wenn sich der Punkt im "in"-Bild innerhalb des "in2"-Bildes befindet. Oder anders ausgedrückt: Verwende für den Ergebnis-Bildpunkt den RGBA-Wert des "in" Bildes und wende auf diesen Punkt zusätzlich den Transparenzwert des Bildpunktes aus "in2" an.

Das unterste Bildfeld zeigt die Kombination des grünen Schattenfeldes mit dem Originalbild. Hier wird wiederum feComposite benutzt, diesmal aber mit operator="over". Dieser Operator zeichnet das "in"-Bild über das "in2" Bild. Nur dort, wo ein Bildpunkt in "in" Transparenz besitzt, ist "in2" erkennbar.

     <feComposite in="SourceGraphic" operator="over" in2="greenShadow" result="ergebnis" />


Maßeinheiten und Filterregionen

Dieses Beispiel nutzt für einige SVG-Attribute die Defaultwerte des Browsers. Vollständig sähe der Filter so aus:

Filter mit ausgefüllten Defaults
    <filter id="soft-3" x="-10%" y="-10%" width="120%" height="120%" 
                          filterUnits="objectBoundingBox" 
                          primitiveUnits="userSpaceOnUse">
      <feGaussianBlur stdDeviation="2.2" />
    </filter>

Ein Filter kann auf ein Element oder eine Gruppe von Elementen angewendet werden. Die Größe des RGB-Bildes, das dann als Eingabe für den Filter entsteht, wird durch das kleinstmögliche Rechteck bestimmt, das alle betroffenen Elemente einschließt. Dieses Rechteck nennt man Bounding-Box. Es ist aber oftmals so, dass das Filterergebnis größer als die Bounding-Box ist, d.h. für das Filterergebnis, das nachher vom Browser ausgegeben wird, braucht man etwas mehr Platz. Dieses Rechteck ist die Filterregion, und seine Größe und Lage in Bezug auf die Bounding-Box lässt sich mit den Attributen x, y, width und height festlegen. Der Normalfall ist, dass die Filterregion die BoundingBox in allen Richtungen um 10% ihrer Größe überragt. Eine stärkere Unschärfe oder Verschiebungseffekte benötigen möglicherweise eine größere Filterregion.

Die Maßeinheit für die Filterregion wird mit dem Attribut filterUnits festgelegt. Der Standardwert ist objectBoundingBox. Das bedeutet, dass der Wert 100% für Breite oder Höhe die vollständige Breite bzw. Höhe der Bounding-Box des Filters bezeichnet, ganz gleich, wie groß die Bounding-Box tatsächlich ist. Gibt man statt dessen userSpaceOnUse an, beziehen sich die angegebenen Werte auf das Koordinatensystem, das für das gefilterte Element verwendet wird. Zumeist ist das unpraktisch, weil der Filter dadurch auf eine bestimmte Größe der Bounding-Box festgelegt wird.

Bei den Filtereffekten ist es anders. Die meisten von ihnen unterstützten ebenfalls die Angabe von x, y, width und height, um einen Teilbereich der Filterregion festzulegen, in den sie ihr Ergebnis schreiben dürfen. Das Filterattribut primitiveUnits legt die Maßeinheit für diese Teilbereiche fest, und hier ist der Standardwert userSpaceOnUse. In den meisten Fällen ist die Angabe von Teilbereichen allerdings unnötig, standardmäßig wirkt jeder Filtereffekt auf die gesamte Filterregion.


Filter ermöglichen pixelorientierte Manipulationen an SVG-Vektorgrafiken und Elementen. Zum einen gibt es einige vordefinierte Filter, die als CSS-Funktionen notiert werden können. Zum anderen lassen sich mit SVG-Elementen auch eigene Filter aus einem oder beliebig vielen Filtereffekten zusammensetzen (man nennt diese Effekte auch Urfilter oder Primitive). Die Filtereffekte werden mit Hilfe von SVG-Elemente erzeugt, die man daran erkennt, dass ihr Name mit fe (Filtereffekt) beginnt.[2]

Filter-Universalattribute und Filterkoordinatensystem

Außer id kennen das filter-Element und die Filtereffekt-Elemente eine Reihe von "Filter-Universalattributen":

  • x: X-Koordinate
  • y: Y-Koordinate
  • width: Breite
  • height: Höhe

Diese legen die Region fest (den Begrenzungsrahmen), innerhalb dessen der Filter wirkt. Der Koordinatenursprung ist dabei SVG-typisch die obere linke Ecke der Eingangsgrafik. Welche Koordinatenwerte zu verwenden sind, ist mit der Eigenschaft filterUnits einstellbar. Diese legt standardmäßig objectBoundingBox fest, Vorlage:DH man kann Prozentwerte benutzen, um Größenangaben zu machen. Der Bezugswert für diese Prozentwerte ist ein Rechteck, das gerade so groß ist, ess es alle SVG-Elementen, auf die der Filter wirkt, einschließt.

Solange nichts anderes angegeben wird, ist die Filterregion auf x="-10%", y="-10%", width="120%" und height="120%" festgelegt.

Die Filtereffekt-Elemente besitzen diese Attribute ebenfalls, um den Wirkungsbereich (die Teilregion) für den Effekt zu begrenzen. Das Koordinatensystem kann abweichen: es wird durch die Eigenschaft primitiveUnits ist das gleiche wie für den Filter, aber der Standardwert für Teilregionen ist 0% für x und y sowie 100% für width und height.

Für das filter-Element ist es standardmäßig so, dass der BegrenzuEinflussbereich eines Filters den Bereich, auf das er angewendet wird, um 10% seiner Größe in jeder Richtung, d.h. der Standardwert für x und y ist 10% und der Standardwert für width und height ist 120%. Im Normalfall genügt das, aber mache Filtereffekte ragen weiter über das Element hinaus, auf das man sie anwenden möchte, und man muss die Werte nach Bedarf anpassen, damit der Effekt vollständig sichtbar ist.

Andersherum kann es auch sein, dass der Wirkungsbereich zu groß ist. Hier sollte aber zuerst geprüft werden, ob nicht die Verwendung des feComposite-Filterelements mit der operation="in" und in2="SourceAlpha" die bessere Lösung ist.

Ob sie gebraucht werden, hängt vom jeweiligen Filter ab und davon, ob bzw. welche Angaben schon im filter-Tag gemacht wurden.

Empfehlung: Teste, ob der gewählte Begrenzungsrahmen für die Filter ausreicht, da manche Filter das Bild vergrößern. Darüber hinaus ist anzuraten, den Begrenzungsrahmen immer um einige Prozent zu vergrößern, da manche Filter die Grafik etwas ausdehnen.


Eingangswert in

Kommen in einer Filterdefinition mehrere Filtertypen zum Einsatz, ist üblicherweise deren Reihenfolge wichtig, da das Resultat des letzten Filtertyps dem nächsten als Eingabe dient. Der erste Filtertyp nutzt die Eingangsgrafik.

Man kann allerdings mit den Attributen in und result ein anderes Verhalten festlegen. Für in sind folgende Attributwerte definiert:

  • SourceGraphic: (Standardwert) ganze Ausgangsgrafik
  • SourceAlpha: benutzt Alphakanal der Ausgangsgrafik
  • filterergebnis: Ein beliebiger Name, der bei einem anderen Filtereffekt im result-Attribut angegeben wurde. Auf diese Weise können Filter hintereinandergeschaltet werden.
diverse Modi für das in-Attribut ansehen …
<defs>
	<filter id="sGraphic">
		<feGaussianBlur stdDeviation="4" in="SourceGraphic"/>
	</filter>
	<filter id="sAlpha">
		<feGaussianBlur stdDeviation="4" in="SourceAlpha"/>
	</filter>
	<filter id="bgImage">
		<feGaussianBlur stdDeviation="4" in="BackgroundImage"/>
	</filter>
	<filter id="bgAlpha">
		<feGaussianBlur stdDeviation="4" in="BackgroundAlpha"/>
	</filter>
	<filter id="fPaint">
		<feGaussianBlur stdDeviation="4" in="FillPaint"/>
	</filter>
	<filter id="sPaint">
		<feGaussianBlur stdDeviation="4" in="StrokePaint"/>
	</filter>
</defs>
 
<g transform="translate(100,50)">
	<text y="-5">Kein Filter</text>
	<rect width="150" height="100" />
	<circle cx="50" cy="100" r="50" />
</g>
...

Das Beispiel zeigt ein Rechteck und davor einen Kreis. Durch die Festlegung fill-opacity:.5 im CSS haben beide einen halbtransparenten Hintergrund. Der Filter feGaussianBlur wird jeweils auf den Kreis angewandt, mit 6 verschiedenen in-Werten.

Pseudo inputs

Beachte:

Die folgenden Werte sind in der Spezifikation (auch in SVG2) enhalten, werden von den Browsern jedoch nicht unterstützt:[3]

  • Firefox stellt die Werte BackgroundImage, BackgroundAlpha nicht dar
  • Safari nicht BackgroundImage, BackgroundAlpha, FillPaint, StrokePaint
  • Chrome, Edge und Opera stellt BackgroundImage, BackgroundAlpha, FillPaint, StrokePaint als sourceGraphic dar
  • BackgroundImage: verändert Bildausschnitt des SVG-Dokuments unter dem Filterbereich. Dafür muss das gefilterte Objekt Teil einer Gruppierung sein, die das Attribut enable-background="new" enthält
  • BackgroundAlpha: verändert Alphakanal des Bildausschnitts unter dem Filterbereich. Dafür muss das gefilterte Objekt Teil einer Gruppierung sein, die das Attribut enable-background="new" enthält
  • FillPaint: verändert den Wert der fill-Eigenschaft
  • StrokePaint: verändert den Wert der stroke-Eigenschaft

Ergebniswert result

Mit dem result-Attribut kann man auch einen Namen für das Ergebnis eines Filtertyps vergeben, und dann diesen Namen anstelle eines der obigen Attributwerte mit in in einem anderen Filtertyp als Eingangswert nutzen.

Beispiel ansehen …
<defs> <filter id="Filter"> <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="weichgezeichnet"/> <feSpecularLighting in="weichgezeichnet"/> surfaceScale="5" specularConstant="1" specularExponent="10" lighting-color="white" result="zwischenergebnis1"/>> <fePointLight x="-50" y="-100" z="200"/> </feSpecularLighting> <feComposite in="zwischenergebnis1"/> in2="SourceAlpha" operator="in" result=zwischenergebnis2"/> <feComposite in="SourceGraphic" in=zwischenergebnis2" operator="arithmetic" k1="0" k2="1" k3="1" k4="0" in=beleuchtet"/> <!-- Weichzeichner --> <feGaussianBlur in="SourceAlpha" stdDeviation="3" result=weichgezeichnet1"/> <!-- Verschiebung --> <feOffset in=weichgezeichnet1" dx="3" dy="3" result="weichgezeichnetVerschoben"/> <!-- Zusammenfügen --> <feMerge> <feMergeNode in="weichgezeichnetVerschoben"/> <feMergeNode in="SourceGraphic"/> <feMergeNode in=beleuchtet"/> </feMerge> </filter> </defs>

Die Ergebniswerte result der einzelnen Filter werden als Eingangswerte in für neue Filter verwendet.

Urfilter

Filter ermöglichen pixelorientierte Manipulationen an SVG-Vektorgrafiken und Elementen. Man kann beliebig viele Filtertypen in einem Filter kombinieren. Filterelemente erkennt man am Präfix "fe", das für "Filtereffekt" steht.



Weblinks

  1. Wikipedia: Gaußscher Weichzeichner
  2. Wikibooks: SVG (von 2012, aber gut erklärt und gute Beispiele])
  3. vanseodesign: SVG Filter Primitives—Input and Output Steven Bradley