SVG/Tutorials/Text/Filter-Effekte

Aus SELFHTML-Wiki
< SVG‎ | Tutorials‎ | Text
Wechseln zu: Navigation, Suche

Unter Grafikfiltern versteht man Funktionen in einer Grafiksoftware, die ein bestehendes digitales Bild mit einem vorprogrammierten Algorithmus gezielt verändern. Der Begriff lehnt sich an die Filter im Bereich der Fotografie an.

Mit SVG-Filtern haben Sie viele Möglichkeiten für grafische Pixelmanipulationen, die das Repertoire des Webdesigners erweitern. Dabei gibt es viele spektakuläre Möglichkeiten, aber auch zwei Nachteile:

  • SVG-Filter verändern das Original-Bild nicht (nicht-destruktive Bearbeitung[1]), berechnen beim Laden aber immer wieder alles neu, komplexere Filter bringen so leistungsschwächere Mobilgeräte zum Glühen und Ruckeln.
  • der Aufbau mit vielen Urfiltern und XML-Attributen ist eher etwas für Raketenwissenschaftler als für den Hobby-Entwickler.

Dies ist heute besser geworden. Filter sind heute Bestandteil von CSS[2]; mit der CSS-filter-Eigenschaft können viele Algorithmen bequem in HTML, aber auch in SVG eingebunden werden.

SVG-Filter in CSS

Das Konzept der SVG-Filter wurde in die CSS filter-Eigenschaft übernommen. Dabei können entweder Standardeinstellungen verwendet oder eigene SVG-Filter verwendet werden.

Dieses Beispiel zeigt eine Auswahl von Filtern, die SVG-Text verändern[3]:

CSS-Filter-Funktionen ansehen …
.blur {
	filter: blur(0.08em);
}
.schatten1 {
	filter: drop-shadow(1px 1px 0 black);
}

.schatten2 {
	filter: drop-shadow(1px 1px 2px #333);
}

.glow {
	fill: #c82f04;
  animation: svg-glow 2s  infinite alternate;
}

@keyframes svg-glow {
  from {
    filter: drop-shadow( 0 0 0 #fff) drop-shadow( 0 0 0 pink) drop-shadow( 0 0 0 white);
  }

  to {
    filter: drop-shadow( 0 0 1px red) drop-shadow( 0 0 2px pink) drop-shadow( 0 0 4px white);
  }
}
Empfehlung: Für Weichzeichner, Schatten und einfache Beleuchtungseffekte sind die hier vorgestellten CSS-Funktionen viel einfacher als die weiter unten vorgestellten SVG-Urfilter.

Referenz zu einem <filter> Element

Die filter-Eigenschaft erhält als Wert im Allgemeinen vordefinierte CSS-Filter. Sie können aber auch komplexere SVG-Filter einbinden, die Text entsprechend verändern.[4]

Wackelpeter ansehen …
.squiggly {
  animation: squiggly-anim 0.5s linear infinite;
  filter: url("#squiggly-0");
}

@keyframes squiggly-anim {
  0% {
    filter: url("#squiggly-0");
  }
  25% {
    filter: url("#squiggly-1");
  }
  50% {
    filter: url("#squiggly-2");
  }
  75% {
    filter: url("#squiggly-3");
  }
  100% {
    filter: url("#squiggly-4");
  }

Im folgenden Beispiel wird einem div innerhalb eines HTML-Dokuments per CSS über die url()-Funktion ein Filter zugeordnet. Durch eine CSS-Animation wird dieser Filter mit vier anderen immer wieder ausgetauscht.

Diese Filter sind im Definitionsabschnitt des SVG notiert.

der oben referenzierte Filter im Definitionsabschnitt
<svg xmlns="http://www.w3.org/2000/svg" >
  <defs>
    <filter id="squiggly-0">
      <feTurbulence baseFrequency="0.02" numOctaves="3" result="noise" seed="0"/>
      <feDisplacementMap id="displacement" in="SourceGraphic" in2="noise" scale="6" />
    </filter>
    <filter id="squiggly-1">
      <feTurbulence baseFrequency="0.02" numOctaves="3" result="noise" seed="1"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="8" />
    </filter>
    
    <filter id="squiggly-2">
      <feTurbulence baseFrequency="0.02" numOctaves="3" result="noise" seed="2"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" />
    </filter>
    <filter id="squiggly-3">
      <feTurbulence baseFrequency="0.02" numOctaves="3" result="noise" seed="3"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="8" />
    </filter>
    
    <filter id="squiggly-4">
      <feTurbulence  baseFrequency="0.02" numOctaves="3" result="noise" seed="4"/>
<feDisplacementMap in="SourceGraphic" in2="noise" scale="6" />
    </filter>
  </defs> 
</svg>

Da 5 Filter notiert sind, scheint das Markup ziemlich schwierig. Die dort verwendeten Urfilter werden in den folgenden Beispielen besprochen.

Schatten

Auf vielen älteren Webseiten finden sich Beispiele für SVG und Schlagschatten, die mit einer Wiederholung der text-Elemente arbeiteten.

Layering: Elemente werden mehrfach übereinander gelegt!
<svg>
  <text x="22" y="202" stroke-width="2" stroke="black">Schlagschatten</text>
  <text x="20" y="200" stroke-width="0" stroke="green">Schlagschatten</text>
</svg>

Der gleiche Text wird einmal an der gewünschten Position und noch einmal um 2px nach rechts und unten versetzt dargestellt. Die dunkle Randlinie sieht wie ein Schatten aus.

Beachten Sie: Das sogenannte Layering von mehreren identischen Text-Elementen wurde früher häufig praktiziert, ist aber nicht barrierefrei.
Screenreader würden den Text zweimal vorlesen - dieses Beispiel soll nur zum dann barrierefreien Endergebnis hinführen!

Heutzutage können Sie diesen Effekt auch mit HTML und der CSS-Eigenschaft text-shadow, bzw. box-shadow oder der oben bereits vorgestellten drop-shadow()-Funktion erreichen.

Reflektion

Ein Schattenwurf, in dem der Text gespiegelt als Schatten geworfen wird, ist ohne Layering nicht möglich. Dabei wird das zweite Text-Element transformiert.

gespiegelt durch Verdopplung und Transformation ansehen …
<svg viewBox="0 0 440 225">
  <text fill="url(#verlauf)" transform="scale(.5,1)"  >
    Reflektion
  </text>
  <text fill="url(#schatten)" role="none" transform="translate(30,165) skewX(25) scale(.5,-.65)">
    Reflektion
  </text>
</svg>

Damit der eigentliche Text höher (und schmaler) wirkt, wird er um den Faktor (0.5,1) gestreckt. Der Schatten wird mit skew(25) verzerrt und dann mit translate(30,165) an die richtige Stelle verschoben.

Damit der Schattenwurf von Screenreadern nicht vorgelesen wird, erhält er als Dekorationsgrafik ein role="none".

Innenschatten

Während Schlagschatten mit der oben erwähnten drop-shadow()-Funktion erzielt werden können, ist dies für Innenschatten nicht möglich, weil es kein inset-Schlüsselwort gibt. Hier helfen aber herkömmliche Filter-Elemente:

Innenschatten ansehen …
<filter id="inset-shadow">
    <feComponentTransfer in="SourceAlpha">
        <feFuncA type="table" tableValues="1 0" />
    </feComponentTransfer>
    <feGaussianBlur stdDeviation="2"/>
    <feOffset dx="5" dy="5" result="Schatten"/>
    <feFlood flood-color="black" result="Farbe"/>
    <feComposite in="Farbe" in2="Schatten" operator="in"/>
    <feComposite in2="SourceAlpha" operator="in" />
    <feMerge>
        <feMergeNode in="SourceGraphic" />
        <feMergeNode />
    </feMerge>                    
</filter>

Aus dem Alphakanal der Eingangsgrafik wird ein Schatten erzeugt. Dieser wird erst mit einer durch feFlood erzeugten Fläche und dieses Zwischenergebnis wieder mit dem Alphakanal vermischt. Das Ergebnis wird mit der Ausgangsgrafik zusammengefügt.

Im unteren Beispiel wurde nur der Wert für stdDeviation für den feGaussianBlur-Filters vergrößert, sodass der Schatten weicher wirkt und die flood-color von feFlood aus weiß geändert.

Empfehlung: Lassen Sie den feComponentTransfer-Filter weg und beobachten Sie die Veränderung.

Beleuchtungseffekte

Beleuchtungseffekte wie in den folgenden Beispielen können Sie nur mit SVG realisieren; mit CSS lassen sie sich nicht erzielen.

Licht und Beleuchtung ansehen …
<filter id="Licht" filterUnits="userSpaceOnUse">
    <feGaussianBlur in="SourceAlpha" stdDeviation="4" result="schatten"/>
    <feOffset in="schatten" dx="4" dy="4" result="Schlagschatten"/>
    <feSpecularLighting surfaceScale="5" specularConstant=".75"
                    specularExponent="20" lighting-color="white" in="schatten"
                    result="beleuchtet">
        <fePointLight x="-500" y="-1000" z="2000"/>
    </feSpecularLighting>
    <feComposite operator="in" in="beleuchtet" in2="SourceAlpha"  result="beleuchtet2"/>
    <feComposite operator="arithmetic" in="SourceGraphic" in2="beleuchtet2" k1="0" k2="1" k3="1" k4="0"  result="beleuchtet3"/>
    <feMerge>
        <feMergeNode in="Schlagschatten"/>
        <feMergeNode in="beleuchtet3"/>
    </feMerge>
</filter>

Es wird mit feGaussianBlur ein Schatten erzeugt, der dann mit feOffset verschoben wird. Dieser Ergebniswert dient als Schlagschatten, aber auch als Eingangswert schatten für den Beleuchtungseffekt.

Der Wischeffekt des Schattens sorgt für eine abgerundete Oberfläche der Alphawerte, die durch den Beleuchtungseffekt mit dem feSpecularLighting-Filter hervorgehoben werden.

Der erste feComposite-Filter beschneidet die überliegenden Ränder außerhalb der Originalgrafik; der zweite feComposite-Filter legt die beleuchtete Fläche über die Eingangsgrafik.

Im unteren Beispiel ist anstelle des Punktlichts ein feDistantLight-Filter verwendet worden.

goldig

Dieses Beispiel wurde 2009 von Vincent Hardy auf der SVG-WOW vorgestellt.[5]

komplexe Beleuchtungs- und Schatteneffekte ansehen …
<filter id="edel" filterUnits="userSpaceOnUse" x="0" y="0" width="880" height="500">
    <feFlood flood-color="black"  result="textur"/>
    <feMerge result="texturUndGrafik">
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
    </feMerge>

    <feDiffuseLighting in="textur" surfaceScale="2" lighting-color="white"
          diffuseConstant="1" result="backgroundDiff">
          <feSpotLight id="spotLight" x="50" y="50" z="150"
                pointsAtX="150" pointsAtY="150" pointsAtZ="0"
                specularExponent="8" />
    </feDiffuseLighting>

    <feGaussianBlur in="SourceAlpha" stdDeviation="6" result="blur"/>
    <feDiffuseLighting in="blur" surfaceScale="6" lighting-color="white"
         diffuseConstant="1.2" result="foregroundDiffAll">
        <feDistantLight id="distantLight" azimuth="-135" elevation="40" />
    </feDiffuseLighting>
    <feComponentTransfer>
        <feFuncR type="gamma" amplitude="1" exponent="3" offset="0"/>
        <feFuncG type="gamma" amplitude="1" exponent="3" offset="0"/>
        <feFuncB type="gamma" amplitude="1" exponent="3" offset="0"/>
    </feComponentTransfer>
    <feComposite operator="in" in2="SourceAlpha"/>
    <feConvolveMatrix order="3" kernelMatrix="0.0625 0.0625 0.0625
                                              0.0625 0.5    0.0625
                                              0.0625 0.0625 0.0625"
                                  result="foregroundDiff"/>

    <feMerge result="diff">
        <feMergeNode in="backgroundDiff" />
        <feMergeNode in="foregroundDiff" />
    </feMerge>

    <feColorMatrix type="luminanceToAlpha" in="diff" result="screenMask"/>
    <feComponentTransfer result="multiplyMask">
        <feFuncA type="linear" slope="-1" intercept="1"/>
    </feComponentTransfer>

    <feBlend mode="screen" in2="texturUndGrafik" in="diff" result="screen"/>
    <feBlend mode="multiply" in2="texturUndGrafik" in="diff" result="multiply"/>

    <feComposite operator="in" in="screen" in2="screenMask" result="maskedScreen"/>
    <feComposite operator="in" in="multiply" in2="multiplyMask" result="maskedMultiply"/>

    <feComposite operator="arithmetic" in="maskedScreen" in2="maskedMultiply"
          k1="0" k2="1" k3="1" k4="0" result="background" />

    <feMorphology operator="dilate" in="SourceAlpha" radius="4" />
    <feGaussianBlur stdDeviation="4" result="blur"/>
    <feOffset id="offset" dx="12" dy="12" result="offsetBlur"/>
    <feComposite in2="SourceAlpha" operator="out" result="shadow" />

    <feMerge>
        <feMergeNode in="background" />
        <feMergeNode in="shadow"/>
    </feMerge>
</filter>

Dieser Filter beinhaltet insgesamt 21 Urfilter um den metallischen Effekt zu erzielen.

Der durch feFlood erzeugte Hintergrund wird durch einen feDiffuseLighting-Filter beleuchtet.

Der Text wird ebenfalls so beleuchtet, nachdem die Werte des Alphakanals unscharf maskiert und mit feComponentTransfer verändert wurden.

Mit feGaussianBlur, feMorphology, feOffset und feComposite wird ein zusätzlicher Schlagschatten erzielt.

Mit mehreren feMerge- und feComposite-Filtern werden die verschiedenen Ebenen wieder übereinander gelegt.

Turbulenzeffekte

Webseiten sind oft monoton strukturiert. Anders als in der Natur bestehen sie aus geraden Linien und Rechtecken, die Farben sind oft flächig, nur manchmal sorgen Verläufe für etwas Abwechslung.

Mit dem feTurbulence-Filter können Sie Strukturen mit unregelmäßigen Mustern erzeugen. Sie wirken oft natürlicher und abwechslungsreicher.

vom Krümelmonster abgebissen

Schriften sehen immer gleich oder zumindest ähnlich aus, obwohl mit font-face auch andere Schriftarten eingebunden werden können. Mit diesem Filter können Sie gewohnte Glyphen in ihrer Form ändern, indem Teile „gerissen“ oder „abgebissen“ werden:

eingerissen oder abgebissen? ansehen …
    <filter id="gerissen" filterUnits="userSpaceOnUse" x="0" y="-100" >
      <feTurbulence result="Rauschen" 
	      baseFrequency="0.08"
          numOctaves="1" 
		  seed="1" />
       <feDisplacementMap in="SourceGraphic" in2="Rauschen" scale="9" />
    </filter>

Mit dem feTurbulence-Filter wird eine mit fraktalem Rauschen gefüllte Fläche erzeugt. Diese wird mit feDisplacementMap als Verschiebekarte für den Text benutzt, sodass er nicht mehr mit glatten Rändern, sondern wie aus gerissenem Papier aussieht.

Das mittlere text-Element verwendet den gleichen Filter, wird durch den breiten Rand und die Unterschiede zwischen Rand- und Füllfarbe aber ganz anders dargestellt.

Sprayeffekt

Mit diesem Sprayeffekt werden die scharfen Ränder der Glyphen durch eine Punktewolke ersetzt, die den Eindruck eines Graffitis vermittelt.

gepunktete Sprayeffekte ansehen …
    <filter id="spray" filterUnits="userSpaceOnUse" x="0" y="-100" >
      <feTurbulence
          type="fractalNoise"
          baseFrequency="1.95"
          numOctaves="4"
          seed="11865"
          stitchTiles="noStitch" />
      <feComponentTransfer result="in2">
        <feFuncR type="linear" slope="2" intercept="-0.7" />
        <feFuncG type="linear" slope="1.5" intercept="-0.5" />
        <feFuncB type="linear" slope="1.5" intercept="-0.5"  />
        <feFuncA type="linear" slope="0" intercept="1" />
      </feComponentTransfer>
      <feDisplacementMap in="SourceGraphic" in2="in2" result="V"
          scale="20"
          xChannelSelector="R"
          yChannelSelector="G" />
    </filter>

Mit dem feTurbulence-Filter wird eine mit fraktalem Rauschen gefüllte Fläche erzeugt. Diese wird mit feDisplacementMap als Verschiebekarte für den Text benutzt, sodass er nicht mehr mit glatten Rändern, sondern als Ansammlung von Punkten dargestellt wird.

Zeitung im Knitterlook

Diese Filtereffekte kann man nicht nur auf den Text selbst, sondern auch auf einen ganzen Artikel anwenden. Hier ist es ein HTML-div mit mehreren Text-Absätzen, die durch einen Filter verändert werden:

Knitterlook durch Verzerrung ansehen …
<filter id="distort"> 
  <feTurbulence baseFrequency="0.005 0.005" numOctaves="1" result="noise" /> 
  <feDisplacementMap in="SourceGraphic" in2="noise" scale="9" /> 
</filter>

Wie in den oberen Beispielen erzeugt der feTurbulence-Filter ein fraktales Rauschen. Diese wird als noise mit der Ursprungsgrafik (SourceGraphic) vermischt.

Das div erhält so einen unregelmäßigen Rand und wirkt geknickt, an den Knickstellen werden die Buchstaben unleserlich.

Beachten Sie:
Testen Sie, ob die Lesbarkeit noch gegeben ist und stellen Sie die Werte im Zweifelsfall geringer ein.
Inhalt geht vor Glitzereffekt!

wolkig

Beispiel ansehen …
<defs>
<filter id="wolke">
    <feTurbulence type="turbulence" baseFrequency="0.055" numOctaves="5"/>
    <feColorMatrix type="luminanceToAlpha"/>
    <feColorMatrix type="matrix" values="0 0 0 -1 1    0 0 0 -1 1    0 0 0 -1 1   0 0 0 0 1"/>
    <feComponentTransfer>
        <feFuncR type="table" tableValues="0   0    0   .4  1"/>
        <feFuncG type="table" tableValues="0   .15  .5  .9  1"/>
        <feFuncB type="table" tableValues="0   0    1   1  1"/>
        <feFuncA type="linear" slope="1" intercept="0"/>
    </feComponentTransfer>
</filter>

<mask id="textMask">
    <text style="fill:white;" x="10" y="60">
         Wolke
    </text>
</mask>
</defs>

<text x="10" y="60" filter="url(#wolke)" mask="url(#textMask)">
    Wolke
</text>

In diesem Beispiel wird mit dem Filter #wolke eine wolkenähnliche Textur erzeugt. Da diese eine rechteckige Fläche hat, wird sie dann in einer Maske, die aus dem selben Text in derselben Größe besteht, über den Text gelegt.

fleckig

Kein Schatten mehr, sondern eher ein Hintergrundmuster …

Der Blob ansehen …
<filter id="blob">
    <feGaussianBlur in="SourceAlpha" result="blurOut" stdDeviation="10"/>
    <feComponentTransfer in="blurOut" result="dropBlur">
        <feFuncA type="table" tableValues="0 .5 0 .5 0 .5 0 .5"/>
    </feComponentTransfer>
    <feComposite operator="over"
                 in="SourceGraphic" in2="dropBlur" />
</filter>


Siehe auch

  • Licht und Schatten
    • Schattierungen
    • Verläufe
  • Filter in SVG
    • Licht und Schatten
    • Bildmanipulation
  • Typografie: Farbe und Dekoration
    • Text und Farbe
      • Füllungen und Konturen
      • Schatten und 3D-Effekte
    • Text-Dekoration

Weblinks

  1. Nicht-destruktive Bearbeitung (de.wikipedia.org)
  2. W3C: Filter Effects Module Level 1 (Editor's Draft)
  3. W3C: SVG Text Effects Gallery alte Beispiele aus dem Jahr 2000
  4. adobe.com: How to Create Squiggly Text with SVG Filters verschnörkelte, unregelmäßige Buchstaben
  5. svg-wow.org von Vincent Hardy