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. Auch wenn sich mittlerweile einige der Effekte mit CSS realisieren lassen, erweitern diese Texteffekte doch das Repertoire des Webdesigners. Mit der filter-Eigenschaft kann man diese SVG-Filter nun auch in HTML selbst einsetzen.

Schatten

Auf vielen älteren Webseiten finden sich Beispiel für SVG und Schlagschatten. Heutzutage können Sie diesen Effekt auch mit HTML und der CSS-Eigenschaft text-shadow erreichen.

Schlagschatten mit Verlauf

Mit diesem Beispiel können Sie Text mit einem scharfen Schlagschatten unterlegen.

Beispiel ansehen …
<svg viewBox="0 0 880 450">
  <defs>
    <linearGradient id="verlauf" gradientTransform="rotate(90,.5,.5)">
      <stop offset="0" stop-color="#fff"/>
      <stop offset=".3" stop-color="#000"/>
      <stop offset=".4" stop-color="#220"/>
      <stop offset=".55" stop-color="#fff"/>
      <stop offset=".65" stop-color="#dfac20"/>
      <stop offset=".75" stop-color="#002"/>
      <stop offset=".9" stop-color="#fff"/>
    </linearGradient> 
  </defs>

  <text x="22" y="202" fill="#200"          stroke-width="2" stroke="#200"  >Schlagschatten</text>
  <text x="20" y="200" fill="url(#verlauf)" stroke-width="0" stroke="#222" >Schlagschatten</text>
</svg>
Der Text wird mit einem Verlauf gefüllt. Dazu wird der gleiche Text noch einmal um 2px nach rechts und unten versetzt dargestellt. Durch die dunkle Randlinie sieht er wie ein dunkler Schatten aus.

Reflektion

Die gleiche Vorgehensweise ermöglicht es Ihnen auch, den Text gespiegelt als Schatten zu werfen. Dabei wird das zweite Text-Element transformiert.


Beispiel ansehen …
<svg viewBox="0 0 440 225">
  <defs>
    <linearGradient id="verlauf" gradientTransform="rotate(90,.5,.5)">
      <stop offset="0" stop-color="#fff"/>
      <stop offset=".3" stop-color="#000"/>
      <stop offset=".4" stop-color="#220"/>
      <stop offset=".55" stop-color="#fff"/>
      <stop offset=".65" stop-color="#884"/>
      <stop offset=".75" stop-color="#002"/>
      <stop offset=".9" stop-color="#fff"/>
    </linearGradient> 
    <linearGradient id="schatten" gradientTransform="rotate(90,.5,.5)">
      <stop offset="0" stop-color="#fff" stop-opacity="0"/>
      <stop offset=".3" stop-color="#000" stop-opacity=".1"/>
      <stop offset=".4" stop-color="#220" stop-opacity=".2"/>
      <stop offset=".55" stop-color="#fff" stop-opacity=".5"/>
      <stop offset=".65" stop-color="#884" stop-opacity=".6"/>
      <stop offset=".75" stop-color="#002"/>
      <stop offset="1" stop-color="#fff"/>
    </linearGradient> 
  </defs>

  <text x="60" y="100" fill="url(#verlauf)" stroke-width=".5" stroke="#222"   transform="scale(.5,1)"  >Reflektion</text>
  <text x="60" y="100" fill="url(#schatten)" transform="translate(30,165) skewX(25) scale(.5,-.65) ">Reflektion</text>
</svg>

Damit der 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.


Schatteneffekte

Alllerdings können solche Effekte auch ohne Verdopplung des Texts, die semantisch nicht sinnvoll ist, erreicht werden. In SVG brauchen wir dafür mehrere Filter:

Beispiel ansehen …
<filter id="Schatten" filterUnits="userSpaceOnUse" x="0" y="0">
    <feGaussianBlur in="SourceAlpha" stdDeviation="4" 
                result="blur"/>
    <feOffset in="blur" dx="10" dy="10"
          result="offsetBlur"/>
    <feMerge>
        <feMergeNode in="offsetBlur"/> 
        <feMergeNode in="blur"/>
        <feMergeNode in="SourceGraphic"/>
    </feMerge>
</filter>
	
<filter id="Leuchten" height="150%" y="-25%">
    <feFlood flood-color="white" />
    <feComposite in2="SourceAlpha" operator="in" />
    <feGaussianBlur stdDeviation="4" />
    <feComponentTransfer>
        <feFuncA type="linear" slope="3" intercept="0" />
    </feComponentTransfer>
    <feMerge>
        <feMergeNode />
        <feMergeNode in="SourceGraphic" />
     </feMerge>
</filter>

Zuerst wird der Alphakanal der Eingangsgrafik mit feGaussianBlur verwischt. Der Wert des stdDeviation-Attributs bestimmt die Größe des Wischeffekts.
Das Ergebnis result="blur" wird zum Eingangswert in="blur" des nächsten Filters.
Um die verwischte Schrift zum Schatten werden zu lassen, wird sie mit feOffset verschoben. Die dx- und dy-Attribute bestimmen, wie weit der Schatten verschoben werden soll.
Damit neben dem Schatten auch die originale Schrift dargestellt wird, wird mit feMerge der Ergebniswert offsetBlur mit der Eingangsgrafik sourceGraphic zusammengefügt.

Im unteren Beispiel wird mit feFlood eine weiße Fläche erzeugt, die dann mit dem Alphakanal vermischt wird. Hier wurden Ergebniswert und Eingangswert weggelassen, nur der zweite Eingangswert in2="SourceAlpha" wird definiert. Mit feComponentTransfer wird der Alphakanal aufgehellt. Das Ergebnis wird dann wieder mit feMerge mit der Eingangsgrafik zusammengefügt. Das erste feMergeNode hat keinen Wert für in, da der Ausgangswert des vorhergehenden Filters verwendet wird.


Innenschatten

Beispiel 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.


fleckig

Beispiel 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>

Kein Schatten, sondern ein Hintergrundmuster...


Beleuchtungseffekte

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

Beispiel 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 feSpecularLighting#feDistantLight-Filter verwendet worden.

goldig

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

Beispiel 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.

gerissen

Beispiel 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 untere Beispiel verwendet den gleichen Filter, wird durch den breiten Rand und die Unterschiede zwischen Rand- und Füllfarbe aber ganz anders dargestellt.


gepunktet

Beispiel 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.

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


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.

SVG-Filter in HTML

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

Im folgenden Beispiel wird ein div innerhalb eines HTML-Dokuments per CSS ein Filter zugeordnet. Dieser [2]

Wackelpeter ansehen …
.squiggly {
  filter: url("#squiggly-0");
}
Die filter-Eigenschaft erhält als Wert im Allgemeinen vordefinierte CSS-Filter. Sie können aber auch komplexere SVG-Filter über die url-Funktion einbinden:

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
  <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>


Weblinks

  1. svg-wow.org von Vincent Hardy
  2. adobe.com: How to Create Squiggly Text with SVG Filters verschnörkelte, unregelmäßige Buchstaben