SVG mask
In der Bildbearbeitung ist das Maskieren mit weichen Konturen mittels Alphakanal eine alte Technik, die seit vielen Jahren im Druck angewendet wird. Da SVG seine Ursprünge in Illustrationsprogrammen wie Illustrator und Corel hat, ist das Maskieren von Bildern mit SVG zuverlässiger als das gleichnamige CSS mask, das zwar inzwischen in Chrome, Firefox und Safari zuhause ist.
Masken bestehen aus einer oder mehreren Formen wie circle, rect, text oder path und in ein mask-Element gelegt werden.
<filter id="blur" x="-.04" y="-.04" width="1.08" height="1.07" style="color-interpolation-filters:sRGB"> <feGaussianBlur stdDeviation="32"/> </filter> <mask id="mask"> <circle cx="490" cy="327" r="300" fill="#fff" filter="url(#blur)" /> </mask>
Das maskierte Element setzt die Maske durch das mask-Attribut und den Verweis auf das mask-Element ein. Dabei spielt es keine Rolle, auf welcher Position die Maske im Markup sitzt: vor oder nach dem maskierten Element. I.d.R. wird die Maske gleich an den Anfang der SVG-Datei gesetzt, oft auch zusätzlich in defs-Tags.
Die maskierte Form oder das Bild wird an allen Stellen außerhalb der Maske durchsichtig. Wie durchsichtig der offene Bereich der Maske wird, hängt von der Helligkeit der Füllfarbe der Maske ab.
<defs> <filter id="blur"> <feGaussianBlur stdDeviation="6" /> </filter> <mask id="mask"> <path id="colored" d="m 680,168 a 313,123 0 1 1 -626,0 313,123 0 1 1 626,0 z" fill="white" filter="url(#blur)" /> </mask> </defs> <image mask="url(#mask)" href="sweet.jpg" y="0" width="720" height="300" />
<path d="m 690,168 …" fill="white" filter="url(#blur)" />
Je dunkler die Füllfarbe der Maske, desto matter wird das darunter liegende Bild angezeigt.
Masken mit weichen Übergängen
Masken wirken entsprechend ihrer Helligkeit: Ein reines Weiß wird vollständig durchsichtig, Grau semitransparent, Schwarz transparent. Eine Farbe wirkt entsprechend ihrer Helligkeit.
Wenn die Maske einen weichen Rand hat, überträgt sich der Übergang auf die maskierte Form. Die einfachste Technik für einen weichen Übergang von Transparent zu gedeckt bietet der SVG Blur-Filter.
<svg viewBox="0 0 980 653" width="100%" height="100%"> <filter id="blur"> <feGaussianBlur stdDeviation="20"/> </filter> <mask id="circlemask"> <circle cx="490" cy="326" r="290" fill="#fff" filter="url(#blur)" /> </mask> <image width="980" height="653" mask="url(#circlemask)" xlink:href="rosen.jpg" /> </svg>
Mehr ist nicht nötig, um ein Bild mit einem weichen Übergang freizustellen. Der SVG-Blur-Filter braucht nur die Angabe einer Stärke (stdDeviation). SVG-Masken reagieren auf die Helligkeit der Maskenfüllung, während bei einem clipPath nur die Kontur des Freistellpads eine Rolle spielt.
Unterschiede: SVG mask vs clipPath
In Hinsicht auf die weiche oder harte Kontur ist mask genereller als clipPath, denn mask ohne Blur-Filter liefert genauso einen harten Rand wie ein clipPath.
Allerdings sollte mask trotzdem i.d.R. dem Freistellen mit einem weichen Übergang zur Transparenz vorbehalten bleiben, denn Maskieren ist eine Raster-Operation mit einem großen Speicherbedarf und langsamer als clipPath.
Masken mit Aussparung – Löchern
Das Loch in der Donut-förmigen Maske wird von einem weiteren circle-Element gebildet und ist mit Schwarz gefüllt.
<mask id="mask5" > <circle cx="340" cy="340" r="290" fill="#fff" filter="url(#blur2)"/> <circle cx="340" cy="340" r="140" fill="#000" filter="url(#blur2)"/> </mask> <image mask="url(#mask5)" xlink:href="little-planet.jpg" x="100" y="30" width="680" height="679" />
Text-Masken
<mask id="myMask"> <rect width="100%" height="100%" fill="#fff" /> <text x="300" y="200" text-anchor="middle" font-size="100" font-family="Arial Black">STOFF</text> <text x="300" y="260" text-anchor="middle" font-size="80" font-family="Arial Black">muster</text> </mask> <image xlink:href="stoff.jpg" width="680" height="416" /> <ellipse mask="url(#myMask)" cx="300" cy="200" rx="240" ry="150" fill="hsla(0,0%,100%,0.8)" />
maskUnits objectBoundingBox | userSpaceOnUse
In gleiche Weise wie clipPathUnits und gradientUnits definiert maskUnits das Koordinatensystem mit dem Attributen x, y, width und height.
- Die Vorgabe ist objectBoundingBox: Die Strecke, über die sich die Maske erstreckt, ist relativ zum maskierten Element.
- userSpaceOnUse ist die Strecke relativ zum Dokument.
Mit relativen Werten und der Voreinstellung objectBoundingBox anstelle absoluter Werte lassen sich Masken direkt auf andere Elemente übertragen.
<mask id="rect"> <rect x="0" y="0" width="50%" height="50%" fill="#444"/> <rect x="50%" y="0" width="50%" height="50%" fill="#888"/> <rect x="0" y="50%" width="50%" height="50%" fill="#aaa"/> <rect x="50%" y="50%" width="50%" height="50%" fill="#ddd"/> </mask> <circle mask="url(#rect)" cx="120" cy="120" r="120" fill="blue"/>
<image mask="url(#rect)" xlink:href="rosen.jpg" width="980" height="653" />
SVG-Formen konstruieren und animieren
Masken werden in SVG nicht nur zum Beschneiden von Bitmap-Bildern verwendet, sondern auch für die Konstruktion komplexer Formen und insbesondere auch für Animationen.
Das mask-Element beschneidet sämtliche Elemente in kompletten Gruppen.
<g id="beach" mask="url(#growingcircle)"> … </g>
Masken können aus einfachen Formen wie circle, rect oder text bestehen, die sich einfach animieren lassen (einfacher als ein Pfad in einem clip-path).
<mask id="growingcircle"> <circle id="showcircle" cx="267" cy="165" r="1" fill="#fff" /> </mask>
Die Animation übernimmt ein kleines Javascript mit wenigen Zeilen (Download Quelltext).
Pattern (Muster) für Masken
Während bei einem clipPath Farbe und Füllung keine Wirkung haben, kann die Form einer Maske gefüllt sein. Darum kann eine Maske auf SVG-Pattern aufsetzen, ein clipPath nicht.
<filter id="sw" style="color-interpolation-filters:sRGB"> <feColorMatrix values="0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0.21 0.72 0.072 0 0 0 0 0 1 0 "/> </filter> <pattern id="pattern" x="0" y="0" width="12" height="12" patternUnits="userSpaceOnUse"> <circle cx="6" cy="6" r="6" fill="#eee"/> </pattern> <mask id="pattern-mask" x="0" y="0" width="1" height="1" > <rect x="0" y="0" width="100%" height="100%" fill="url(#pattern)"/> </mask> <image filter="url(#sw)" mask="url(#pattern-mask)" preserveAspectRatio="xMidYMid slice" … />
preserveAspectRatio="xMidYMid slice" füllt das SVG mit dem Bild, ähnlich wie CSS background-size: cover.