XHTML SVG CSS PHP

Dr. O. Hoffmann

SVG- und PHP-Labor

In der Welt ist es sehr selten mit dem Entweder-Oder getan.
Johann Wolfgang von Goethe

Skalierbare Vektorgraphik - innen und außen

Ein interessantes Problem tritt auf, wenn entschieden werden soll, was innen und was außen ist. Was die fill-Eigenschaft betrifft, nimmt fill-rule dem Autor da eine Menge Arbeit ab, der damit elegant angeben kann, wie seine Pfadangaben gemeint sind. Allgemein gibt in SVG fill die Farbe des inneren Bereiches an, ein SVG-Darstellungsprogramm hat also ein definiertes Verhalten, was die Bedeutung von innen und außen festlegt. Es gibt auch Pfade, die kein Innen und Außen haben, dieses sind einfache gerade Strecken und Punkte, beides kann in SVG dargestellt werden, die Begriffe innen und außen ergeben für diese Pfade keinen Sinn.

Anders sieht die Situation aus, wenn es darum geht, den Rand gezielt zu malen, so daß er etwa nur exakt innerhalb des Gebietes definiert durch einen Pfad gezeichnet wird oder nur exakt außerhalb. Bei einfachen Formen kann der Autor dies natürlich leicht selbst ausrechnen und die Pfadangaben dann modifizieren, allerdings gibt es dann Probleme mit der Skalierbarkeit der Graphik. Das Problem verschärft sich bei Anwendungen wie etwa der Kartographie, wo man natürlich nicht möchte, daß Grenzen zwischen zwei Gebieten, die aneinandergrenzen, überlappen. Gleichzeitig ist es bei Karten natürlich erwünscht, Ausschnitte ohne Verlust der Genauigkeit beliebig zu vergrößern oder zu verkleinern.

Da entsprechende einfache Angaben in SVG bislang (bis Version 1.1) fehlen, muß der Autor auf einige Tricks zurückgreifen. Hier vorgestellt wird, wie mit dem clipPath-Element und der clip-path Eigenschaft einerseits oder dem mask-Element oder der mask-Eigenschaft andererseits das Malen des Randes so eingegrenzt werden kann, daß oben beschriebenes Problem innerhalb von SVG 1.1 gelöst ist. Während clipPath ja nur den Pfad an sich auswertet und keine Farbangaben, ermöglicht mask eine detailliertere Maskierung, weil dort direkt die Farben in eine Teiltransparenz umgerechnet werden. Verwendet man eine reine schwarz-weiß-Maske wie hier, so kann man damit sehr flexibel den zu malenden Bereich eingrenzen. Ähnlich, aber noch flexibler können Filter verwendet werden, die aber erfahrungsgemäß verglichen mit clipPath oder mask mehr Rechenleistung erfordern.

Innen oder außen mit clipPath und clip-path

Der erste Ansatz ist recht einfach. Stellen wir uns vor, eine Karte eines Gebietes liegt als Pfad vor. Ziel ist es, nur den Teil des Randes (stroke) zu malen, der innerhalb des Gebietes liegt. Nach kurzem Überlegen stellen wir fest, daß dies genau der Teil von stroke ist, der auf fill gemalt ist. Ausschneiden kann man dies einfach, indem man dieselbe Pfadangabe nutzt, um den Malbereich einzuschränken. Damit der Pfad nicht mehrmals ins Dokument geschrieben werden muß, wird er einfach einmal angegeben und dann mit use referenziert:
nur den Anteil von stroke auf fill darstellen (Quelltext: Anteil von stroke auf fill darstellen).
In einer Animation wird die Eigenschaft clip-path alle 3s zwischen dem genannten Pfad und none gewechselt, was dann einer kompletten Darstellung von stroke entspricht. Mit einem Klick wird stroke auf none gesetzt, um nur fill zu sehen, also die exakte Form des angegebenen Pfades.

Durch einen weiteren Trick kann auch nur der äußere Anteil von stroke zum Zeichnen ausgewählt werden. Dazu wird einfach die Eigenschaft von innen und außen für die clipPath-Angabe vertauscht. Das geht durch Hinzufügen eines weiteren Pfades um das Gebiet herum, am besten entweder direkt der Rand des Zeichenbereiches oder sogar jenseits davon. Um den Pfad nicht mehrmals angeben zu müssen, wird dieser mit einer Erweiterung der Dokumenttypdeklaration definiert und jeweils im Pfadelement referenziert:
Anteil von stroke außen oder innen darstellen (Quelltext: Anteil von stroke außen oder innen darstellen).
Der innere oder der außere Teil von stroke eines Pfades wird abgetrennt, so daß nur der außerhalb oder innerhalb von fill liegende Anteil dargestellt wird, indem der Pfad selbst als clipPath verwendet wird und mit clip-path angewendet wird. In einer Animation wird die Eigenschaft clip-path alle 3s zwischen dem genannten Pfad innerhalb oder außerhalb und none gewechselt, was dann einer kompletten Darstellung von stroke entspricht. Mit einem Klick wird stroke auf none gesetzt, um nur fill zu sehen, also die exakte Form des angegebenen Pfades.

Innen oder außen mit mask

Ein ähnliches Vorgehen wie bei clipPath führt auch bei mask zum Ziel. Bei Bedarf kann ausgenutzt werden, daß stroke auch zum Maskieren verwendet werden kann, was einem das Vertauschen von innen und außen wie bei clipPath erspart:
Anteil von stroke außen oder innen mit mask darstellen (Quelltext: Anteil von stroke außen und innen mit mask darstellen).
Der innere oder der außere Teil von stroke eines Pfades wird abgetrennt, so daß nur der außerhalb oder innerhalb von fill liegende Anteil dargestellt wird, indem der Pfad selbst als Maske verwendet wird und mit mask angewendet wird. In einer Animation wird die Eigenschaft mask alle 3s zwischen dem genannten Pfad innerhalb oder außerhalb und none gewechselt, was dann einer kompletten Darstellung von stroke entspricht. Mit einem Klick wird stroke auf none gesetzt, um nur fill zu sehen, also die exakte Form des angegebenen Pfades.

Mit einer kleinen Variation des Beispieles lassen sich natürlich auch Muster von Anteilen von stroke darstellen, dabei kommt es darauf an, von außen nach innen jeweils weiße und schwarze Flächen aufeinander zu schichten. Es kann sich dabei als vorteilhaft erweisen, sich bei der Erstellung die Maske selbst erstmal anzugucken, um gezielt den Effekt zu erreichen, den man gerne haben möchte:
mehrere Anteile von stroke darstellen (Quelltext: Mehrere Anteile von stroke darstellen).

Beliebigen Anteil des Randes mit mask anzeigen

Auch bei mask kann man natürlich innen und außen vertauschen, um noch flexibler zu arbeiten. So oder so stellt der Pfad an sich immer einen besonderen Streifen dar, wobei es etwas kniffliger sein kann, wenn der darzustellende Anteil teilweise innen und teilweise außen liegt und dabei noch asymmetrisch zwischen innen und außen verteilt sein soll. Auch das geht natürlich mit etwas Überlegung:
Beliebigen Anteil von stroke darstellen (Quelltext: Beliebigen Anteil von stroke darstellen).

Man beachte, daß in SVG auch nicht geschlossene Pfade ein Innen und Außen haben können. Das kann bei den hier diskutierten Anwendungen zu geringfügigen Überraschungen führen:
Beliebigen Anteil von stroke eines offenen Pfades darstellen (Quelltext: Beliebigen Anteil von stroke eines offenen Pfades darstellen).
Pfad anklickern, um fill-rule zu ändern.

Überraschungen können auch auftreten, wenn eine Kurve sich selbst überschneidet oder wenn sich der Pfad relativ zur stroke-width relativ nahe kommt.
Bei offenen Pfaden wäre es vermutlich sinnvoller, man könnte festlegen, von wie weit links nach wie weit rechts ein Anteil von stroke gemalt werden soll, wobei sich links und rechts relativ zur Richtung bezieht, die sich aus der Angabe der Punkte in der Pfaddefinition ergibt. Das ist in SVG 1.1 nicht vorgesehen, ebensowenig wie einfachere Angaben zu den hier vorgestellten Methoden der Maskierung.

Innen, außen und Filter

Es gibt vielfältige Möglichkeiten, Filter in diesem Zusammenhang anzuwenden. Das folgende Beispiel ist da nicht einmal repräsentativ, weder in der Auswahl der Filtermethoden, noch in den sich ergebenden Resultaten. Hier sind der Phantasie des Autors in beiden Fällen nur weite Grenzen gesteckt, viel Spaß beim Herumprobieren!
Filter anwenden (Quelltext: Filter anwenden). Einige hundert verschiedene Filterkombinationen werden im Sekundentakt angezeigt, einige davon werden sich wiederholen, weil verschiedene Kombinationen zum gleichen Resultat führen. Die Manigfaltigkeit der Anwendungsmöglichkeiten von Filtern ist so groß, daß die hier natürlich nicht einmal ansatzweise durchgespielt werden können.