Ulfs Blog

Baum des Pythagoras
6.2.2017, 8:30

Baum des Pythagoras

Ulfs Blog

Der Schockwellenreiter hat mich inspiriert, den Baum des Pythagoras nur mit SVG ohne Javascript in den Browser zu bringen. Einfache selbstähnliche Figuren lassen sich mit den SVG Elementen <defs> und <use> erzeugen. Für die Rekursion sorgt dann Copy & Paste.

Rekursion in SVG

Als erstes braucht man ein Grundelement, dass in diesem Fall ein Quadrat ist:

<rect id="leaf"
    x="-40" y="0"
    width="80" height="80"
    vector-effect="non-scaling-stroke" />

Das Attribut vector-effect sorgt dafür, dass die Rahmendicke nicht skaliert wird, wenn wir das Quadrat skalieren. Der Rekursionsanfang besteht nur aus dem Grundelement:

<g id="leaf00">
    <use class="leaf00" xlink:href="#leaf"/>
</g>

Man könnte hier auch das Element #leaf direkt nehmen, aber mit einer eigenen Klasse lässt es sich später einfacher einfärben. Anschließend brauchen wir noch die Rekursionsvorschrift (mit XX = YY + 1):

<g id="leafXX">
    <use class="leafXX" xlink:href="#leaf"/>
    <use class="right" xlink:href="#leafYY"/>
    <use class="left" xlink:href="#leafYY"/>
</g>

Man sieht das beim Baum des Pythagoras zuerst das Grundelement .leafXX gezeichnet wird und anschließend das vorherige Element zweimal gezeichnet wird. Den Block muss man so oft kopieren (und dabei die id und die class anpassen), bis man die gewünschte Rekursionstiefe erreicht hat. Die bisherigen Elemente müssen in einem <defs> Element untergebracht werden, so dass sie nicht direkt gezeichnet werden. Zum Schluss wollen wir aber doch etwas sehen. Bei einer Rekursionstiefe von 12 würde das einzige Element außerhalb <defs> so aussehen:

<use xlink:href="#leaf12"
    transform="translate(200, 360) rotate(180)"/>

Da bei SVG die y-Koordinate nach unten zeigt, muss das Bild um 180° gedreht werden.

Transformationen im Stylesheet

Was jetzt noch fehlt sind die Transformationen, die in einem <style> Element definiert werden. Man könnte sie auch jeweils als Attribute in die <use> Elemente schreiben — doch wäre das insbesondere bei Änderungen nicht so übersichtlich:

.left
{
    transform: translate(40px, 80px)
               rotate(-60deg)
               scale(0.5)
               translate(-40px);
}
.right
{
    transform: translate(-40px, 80px)
               rotate(30deg)
               scale(0.866)
               translate(40px);
}

Transformation werden bei SVG von rechts nach links ausgeführt. Die letzte (zuerst ausgeführte) Translation verschiebt den Eckpunkt auf den Koordinatenursprung. Danach werden die Quadrate entsprechend dem Satz des Pythagoras skaliert und rotiert. Die erste (zuletzt ausgeführte) Translation verschiebt den Eckpunkt dann an die entsprechende Ecke des großen Quadrats.

Die Klassen .leaf00 bis .leaf12 brauchen dann noch die SVG spezifische Eigenschaft fill mit der jeweiligen Füllfarbe und das Quadrat <rect> sollte per stroke: #000 und stroke-width: 1 noch einen schwarzen Rahmen erhalten. Damit erhalten wir das folgende schöne Bild:

Ergebnis

Firefox braucht deutlich länger als Chrome, um das Bild zu rendern. Andere Browser habe ich nicht ausprobiert. Was man so liest, ignoriert der IE (wie auch Edge) Transformationen, die per CSS definiert werden.