SVG/ Transformationen
Koordinatensysteme und Transformationen
[Bearbeiten]In SVG können mit diversen Elementen neue Anzeigebereiche eröffnet werden, welche dann mit dem Attribut viewBox auch ein neues Koordinatensystem erhalten. Entsprechend wird eine (implizite) Transformation vom lokalen neuen Koordinatensystem vorgenommen, um den neuen Inhalt im alten Koordinatensystem des umgebenden Elementes darzustellen.
Daneben ist das Attribut transform verfügbar, und zwar bei graphischen Elementen und Gruppierungselementen. Für Farbverläufe und Muster gibt es zudem die verwandten Attribute gradientTransform und patternTransform, um diese Maldienste ebenfalls zu transformieren.
Verfügbar sind in SVG 1.1 und SVG tiny 1.2 affine Transformationen, also solche, die sich durch Matrizen darstellen lassen, welche Objekte vom neuen ins alte Koordinatensystem transformieren. Für einen Autor ist es nützlich, sich etwas mit Matrizenrechnung auszukennen, um die Effekte genau zu verstehen oder eine beliebige Transformation direkt angeben zu können. Für typische und gängige Transformationen stellt SVG allerdings auch einige spezielle Typen bereit, so dass solche Kenntnisse und Fertigkeiten nicht unbedingt notwendig sind.
Attribut transform
[Bearbeiten]SVG | ||||||||
---|---|---|---|---|---|---|---|---|
1.1 | 1.7 | 8 | 3 | 3.2 | 4 | ? | ? | ? |
Mit dem Attribut transform können Gruppierungselemente und graphische Elemente transformiert werden.
Der Wert von transform ist eine Liste von Transformationen, die dann nacheinander ausgeführt werden. Die jeweiligen Transformationen der Liste sind durch Leerzeichen oder Komma separiert.
Die Transformationen werden durch Transformationstypen angegeben, die aus einem Schlüsselwort bestehen, unmittelbar gefolgt von Zahlen in Klammern. Die Transformationen entsprechen Matrizen, welche vom neuen ins alte Koordinatensystem transformieren. Die Matrix beschreibt also mathematisch, welche Koordinaten der transformierte Inhalt im alten Koordinatensystem hat. Koordinaten und Abmessungen des zu transformierenden Elementes und gegebenenfalls der Kindelemente sind also im neuen Koordinatensystem angegeben und werden somit durch die Transformation in das alte, umgebende Koordinatensystem übertragen.
Ist V ein Vektor im neuen Koordinatensystem, so ergibt sich zum Beispiel mit anzuwendenden Transformationen A, B, C der Vektor V' im alten Koordinatensystem:
V' = A * B * C * V, wobei im Attribut transform die entsprechenden Schlüsselwörter in gleicher Reihenfolge notiert sind, also sinngemäß transform="A(...) B(...) C(...)".
Um Verschiebungen mit in die Matrixschreibweise einzubauen, wird ein Trick verwendet. Es wird eine dritte Koordinate eingeführt, die immer 1 ist, ein Vektor sieht dann also wie folgt aus: V = (Vx Vy 1).
Eine Matrix von dieser Art mit den Zahlen a bis f sieht allgemein wie folgt aus:
a | c | e |
b | d | f |
0 | 0 | 1 |
Zu beachten ist dabei, dass eine Vertauschung der Reihenfolge von Transformationsmatrizen meistens zu einem anderen Ergebnis führt. Das ist ein Unterschied zur Multiplikation von einfachen Zahlen.
Das Produkt aller Transformationsmatrizen bis hinauf zum nächstgelegenen Elternelement, welches einen neuen Anzeigebereich eröffnet, wird die aktuelle Transformationsmatrix eines Elementes genannt (englisch: Current Transform Matrix; abgekürzt CTM). Die verbindet also ein Objekt im lokalen Koordinatensystem mit der Darstellung im nächstgelegenen Anzeigebereich. Ist also V ein Vektor zu einem Punkt eines Objektes im lokalen Koordinatensystem, so ist V' = CTM * V die Darstellung im nächstgelegenen Anzeigebereich.
Das Attribut transform ist animierbar mit dem Element animateTransform.
Dazu wird der jeweilige Typ animiert.
Der Typ 'matrix' ist allerdings nicht animierbar.
Näheres dazu ist im Kapitel über Animation erläutert.
Folgendes sind die verfügbaren Transformationstypen (in SVG tiny 1.2 kommen noch eingeschränkte Transformationen hinzu, siehe nächsten Abschnitt):
'translate', Verschiebung
[Bearbeiten]'translate(e f)' spezifiziert eine Verschiebung oder Translation. e ist eine Verschiebung um e in x-Richtung, f ist eine Verschiebung um f in y-Richtung. f ist optional, sofern nicht angegeben, wird 0 angenommen. Ein Beispiel ist also translate(60 40) für eine Verschiebung um 60 in x-Richtung und um 40 in y-Richtung. translate(50) beschreibt eine Verschiebung um 50 in x-Richtung. translate(0 -50) beschreibt eine Verschiebung um -50 in y-Richtung.
Eine Verschiebungsmatrix um e in x-Richtung und f in y-Richtung sieht wie folgt aus:
1 | 0 | e |
0 | 1 | f |
0 | 0 | 1 |
Beispiel Verschiebung
Blaue gerandete Rechtecke werden mittels des Attributes transform vom Typ 'translate' verschoben, so dass ein rotes gerandetes Rechteck komplett verdeckt wird.
Ein grau gerandetes Rechteck zeigt die unverschobene Position.
Gleiche Transformationstypen vertauschen immer miteinander, dies wird mit den dunkler gerandeten Rechtecken angedeutet.
'scale', Skalierung
[Bearbeiten]'scale(a d)' ergibt eine Skalierung. a ist eine Skalierung der x-Richtung entsprechend einer Multiplikation mit a. d ist eine Skalierung der y-Richtung entsprechend einer Multiplikation mit d. d ist optional, sofern nicht angegeben, wird der gleiche Wert wie für a angenommen. Ein Beispiel ist also scale(-1 2), x-Werte werden mit -1 multipliziert, also eine Spiegelung an der y-Achse, y-Werte werden mit zwei multipliziert. Mittels scale(-1) erfolgt eine Punktspiegelung am Ursprung, mit scale(1 -1) eine Spiegelung an der x-Achse. Mit scale(0 1) wird alles auf die x-Achse abgebildet. In SVG 1.1 sind so transformierte Inhalte prinzipiell nicht mehr sichtbar. In SVG tiny 1.2 ergibt sich mit vector-effect="non-scaling-stroke" gegebenenfalls noch ein sichtbarer Strich.
Eine Skalierungsmatrix um a in x-Richtung und d in y-Richtung sieht wie folgt aus:
a | 0 | 0 |
0 | d | 0 |
0 | 0 | 1 |
Beispiel Skalierung
Blaue gerandete Rechtecke werden mittels des Attributes transform vom Typ 'scale' skaliert, so dass rot gerandete Rechtecke komplett verdeckt werden.
Ein grau gerandetes Rechteck zeigt das nicht transformierte Rechteck.
Gleiche Transformationstypen vertauschen immer miteinander, dies wird mit den dunkler gerandeten Rechtecken angedeutet.
'rotate', Drehung
[Bearbeiten]Mit rotate(w x y) wird eine Rotation um einen Winkel w (in Grad) um den Punkt (x, y) vorgenommen. Die positive Drehrichtung geht von der positiven Richtung der x-Achse zur positiven Richtung der y-Achse. x und y sind optionale Angaben, sofern nicht vorhanden, wird 0 angenommen. Zum Beispiel dreht rotate(90) die x-Achse in die y-Richtung und die y-Achse in die -x-Richtung, rotate(-90) die x-Achse in die -y-Richtung und die y-Achse in die x-Richtung. rotate(37 11 -13) beschreibt eine Drehung um 37 Grad um den Punkt (11 -13).
rotate(w x y) ist gleich translate(x,y) rotate(w) translate(-x, -y).
Eine Drehmatrix um den Winkel w um den Ursprung sieht wie folgt aus:
cos(w) | -sin(w) | 0 |
sin(w) | cos(w) | 0 |
0 | 0 | 1 |
Beispiel Drehung
Blaue gerandete Rechtecke werden mittels des Attributes transform vom Typ 'rotate' rotiert, so dass ein rot gerandetes Rechteck komplett verdeckt wird.
Ein grau gerandetes Rechteck zeigt das nicht transformierte Rechteck.
Verschiedene Kombinationen von translate und rotate oder nur rotate können zum gleichen Ergebnis führen, dies wird mit den dunkler gerandeten Rechtecken angedeutet.
'skewX' und 'skewY', Scherung
[Bearbeiten]Eine Scherung in x-Richtung um den Winkel u in Grad wird mit skewX(u) angegeben.
Eine Scherung in y-Richtung um den Winkel v in Grad wird mit skewY(v) angegeben.
Beispiele sind also skewX(30) oder skewY(-45) für eine Scherung in x-Richtung um 30 Grad beziehungsweise -45 Grad in y-Richtung.
Eine Schermatrix um den Winkel u in x-Richtung sieht wie folgt aus:
1 | tan(u) | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
Beispiel Scherung in x-Richtung
Blau gerandete Rechtecke werden mittels des Attributes transform vom Typ 'skewX' geschert, so dass das rot gerandete Rechteck komplett verdeckt wird.
Ein grau gerandetes Rechteck zeigt das nicht transformierte Rechteck.
Gleiche Transformationstypen vertauschen immer miteinander, dies wird mit den dunkler gerandeten Rechtecken angedeutet.
Eine Schermatrix um den Winkel v in y-Richtung sieht wie folgt aus:
1 | 0 | 0 |
tan(v) | 1 | 0 |
0 | 0 | 1 |
Beispiel Scherung in y-Richtung
Blau gerandete Rechtecke werden mittels des Attributes transform vom Typ 'skewY' geschert, so dass das rot gerandete Rechteck komplett verdeckt wird.
Ein grau gerandetes Rechteck zeigt das nicht transformierte Rechteck.
Gleiche Transformationstypen vertauschen immer miteinander, dies wird mit den dunkler gerandeten Rechtecken angedeutet.
Beispiel Scherung
Verschiedene Transformationen vertauschen in der Regel nicht miteinander, auch 'skewX' und 'skewY' nicht.
Das Beispiel zeigt die beiden Möglichkeiten.
Beispiel Scherung in beliebiger Richtung
Um eine Scherung in einer beliebigen Richtung zu erreichen, kann man zum Beispiel die Scherungsrichtung in die x-Richtung drehen, gefolgt von 'skewX', gefolgt von einer erneuten Drehung, diesmal in die umgekehrte Richtung.
Wenn der Scherungswinkel s ist und der Winkel von der x-Achse zur Scherungsrichtung a, dann entspricht dies der Transformation rotate(a) skewX(s) rotate(-a).
Die Graphik links zeigt Beispiele mit s gleich 40 Grad. Die gefüllten Beispiele links entsprechen einer Drehung von 90 Grad. Dabei ist zu beachten, dass dies für 90 Grad skewY(-90) entspricht. Die gerandeten Beispiele rechts zeigen verschiedene Scherungsrichtungen mit einer Differenz von 45 Grad.
Offenbar ergibt sich ein numerisches Problem bei Scherungswinkeln wie 90 Grad oder -90 Grad, allgemein (90 + n*180)Grad mit einer ganzen Zahl n. In solchen Fällen ergibt sich eine unendliche Ausdehnung in der Scherungsrichtung. Die Spezifikationen machen dazu allerdings keine besonderen Angaben, das Darstellungsprogramm muss mit dem Problem selbst fertigwerden.
Beispiel Scherung mit problematischen Winkeln
Zwei Rechtecke werden mittels animateTransform vom Typ 'skewX', beziehungsweise 'skewY' geschert, wobei auch problematische Winkel auftreten.
'matrix', Matrix
[Bearbeiten]Eine allgemeine (affine) Transformation, auch oder gerade wenn sie nicht unter die vorherigen Typen fällt, kann direkt mit matrix(a,b,c,d,e,f) angegeben werden.
Dies entspricht der Matrix:
a | c | e |
b | d | f |
0 | 0 | 1 |
Der Typ 'matrix' ist nicht animierbar. Gründe dafür sind in den Spezifikationen nicht angegeben. Sind alle Zahlen von 'matrix' 0, so unterbindet dies die Anzeige des transformierten Elementes in SVG tiny 1.2.
Beispiel Matrix
Ein großes blau gerandetes Rechteck wird mittels des Attributes transform vom Typ
'matrix' verschoben, so dass ein rotes gerandetes Rechteck komplett verdeckt wird.
Ein grau gerandetes Rechteck zeigt die unverschobene Position.
Transformationen vom Typ 'matrix' vertauschen im Allgemeinen nicht miteinander. Die kleinen Rechtecke zeigen Beispiele dazu.
Eingeschränkte Transformationen
[Bearbeiten]SVG | ||||||||
---|---|---|---|---|---|---|---|---|
1.2 tiny | - | 9.5 | - | - | - | ? | ? | ? |
Mit SVG tiny 1.2 wurde eine Möglichkeit eingeführt, Transformationen einzuschränken, so dass die Koordinaten die gleichen sind wie für das Hauptelement svg.
Es gibt verschiedene Transformationen, die Einfluss auf die Darstellung haben können, zum einen sind dies vom Betrachter initiierte Skalierungen, Translationen oder Drehungen. Zum anderen gibt es die implizit durch viewBox bewirkte Transformationen und schließlich das Produkt aller Transformationen bedingt durch die Attribute transform, welche in Elternelementen notiert sind oder direkt in einem graphischen Element.
Seien die vom Betrachter initiierten Transformationen BS (Skalierung), BT (Translation) und BD (Drehung), insgesamt: B = BT * BS * BD. VS sei die durch viewBox beim Element svg bedingte Transformation. Das Produkt aller Transformationsattribute eines Elementes mit dem Fragmentidentifizierer id bis hinauf zum svg sei TS(id).
Als aktuelle Transformationmatrix CTM gemäß SVG tiny 1.2 ergibt sich somit:
CTM = B * VS * TS(id).
SVG tiny 1.2 führt nun den neuen Transformationstyp 'ref' ein, der die Transformationen ausgenommen B und VS rückgängig macht oder es anders formuliert erlaubt, an beliebiger Stelle im Dokument Elemente anzuordnen, für die das anfängliche Koordinatensystem gilt.
Sofern die inverse Matrix von TS(id) existiert, kann das Ergebnis formal erzielt werden, indem die CTM mit dieser inversen Matrix (von rechts) multipliziert wird. Existiert die inverse Matrix nicht, so muss das Darstellungsprogramm eine andere Methode verwenden, um den gewünschten Effekt zu erreichen, zum Beispiel direkt die Koordinaten als solche im anfänglichen Koordinatensystem interpretieren (was praktisch ein anderes Vorgehen erfordern mag als bei der Darstellung ohne diesen Transformationstyp).
'ref(svg)'
[Bearbeiten]Mittels 'ref(svg)' wird angegeben, dass das Element nicht in lokalen Koordinaten angegeben ist, sondern in denen des anfänglichen Anzeigebereiches (ausschließlich der durch den Betrachter initiierten Transformationen).
Beispiel:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.2" baseProfile="tiny"
xmlns="http://www.w3.org/2000/svg"
xml:lang="de"
viewBox="-100 -100 200 200">
<title>Beispiel eingeschränkte Transformation</title>
<g transform="skewX(30) rotate(45) translate(-20,-20)">
<rect width="40" height="40" fill="green" />
<rect width="40" height="40" fill="blue" transform="ref(svg)" />
</g>
</svg>
Während das grüne Viereck geschert, gedreht und verschoben wird und darauf auch die implizite Transformation durch viewBox wirkt, wird das blaue Quadrat nicht geschert, gedreht oder verschoben, sondern in den Koordinaten des Anzeigebereiches dargestellt, aber gegebenenfalls aufgrund des Malermodells das grüne teilweise verdeckend, weil es später im Quelltext steht.
Beispiel eingeschränkte Transformation
Eine Gruppe mit einem grünen und einem blauen Quadrat wird verschoben, gedreht und geschert.
Für das blaue Quadrat ist die Transformation allerdings eingeschränkt.
Position und Größe entsprechen dem Quadrat mit schwarzem Strich.
'ref(svg, x, y)'
[Bearbeiten]Mittels 'ref(svg, x, y)' wird angegeben, dass das Element nicht in lokalen Koordinaten angegeben ist, sondern in denen des anfänglichen Anzeigebereiches (ausschließlich der durch den Betrachter initiierten Transformationen).
Dabei sind x und y zwei Zahlen, die eine zusätzliche Verschiebung des Elementes
relativ zum anfänglichen Anzeigebereich in Koordinaten des anfänglichen Anzeigebereiches
bewirken.
Beispiel:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.2" baseProfile="tiny"
xmlns="http://www.w3.org/2000/svg"
xml:lang="de"
viewBox="-100 -100 200 200">
<title>Beispiel eingeschränkte Transformation</title>
<g transform="skewX(30) rotate(45) translate(-20,-20)">
<rect width="40" height="40" fill="green" />
<rect width="40" height="40" fill="blue" transform="ref(svg, -20,-20)" />
</g>
</svg>
Während das grüne Viereck geschert, gedreht und verschoben wird und darauf auch die implizite Transformation durch viewBox wirkt, wird das blaue Quadrat nicht geschert, gedreht oder verschoben, sondern in den Koordinaten des Anzeigebereiches dargestellt, aber gegebenenfalls aufgrund des Malermodells das grüne teilweise verdeckend, weil es später im Quelltext steht. Das blaue Quadrat wird zuätzlich im Anzeigebereich verschoben, so dass die linke obere Ecke um -20 horizontal und -20 vertikal verschoben ist (sofern der Betrachter keine zusätzlichen Transformationen veranlasst hat).
Beispiel eingeschränkte Transformation
Eine Gruppe mit einem grünen, blauen und gelben Quadrat wird verschoben, gedreht und geschert.
Für die Gruppe mit dem blauen und dem gelben Quadrat ist die Transformation allerdings eingeschränkt.
Das gelbe wird wiederum auch noch direkt gedreht, diese Transformation ist nicht direkt betroffen, weil
die Eingeschränkung für die umgebende Gruppe angegeben ist.
Position und Größe entsprechen dem Quadrat mit schwarzem Strich.