CSS3: 3D-Effekte mit transform, frei drehbare Pyramide
Bis einschließlich zum CSS2-Standard hatten alle Elemente des DOM eines gemeinsam: Auch wenn sie sich per
z-index auf verschiedenen übereinandergelagerten Ebenen befinden konnten, war nur eine senkrechte, nach oben ausgerichtete Draufsicht auf die Objekte möglich. Dies änderte sich mit CSS3 dahingehend, dass dort nun freie Modifikationen der Elemente im Raum hinsichtlich Maßstabsänderung, Rotation und Verlagerung um alle drei Achsen möglich sind - praktisch werden diese Features, was den 3D-Raum betrifft (im 2D-Bereich ist die Unterstützung breiter), allerdings bisher nur von der Webkit- und Gecko-Engine, also Chrome/Safari sowie Mozilla Firefox korrekt interpretiert. Die beiden Browserfamilien benötigen auch noch Vendor-Präfixe, weshalb im untenstehenden Listing sowohl
-moz als auch
-webkit den Standarddefinitionen vorangestellt werden.
Das folgende Beispiel zeigt - einen passenden Browser vorausgesetzt - eine sich frei im Raum drehende quadratische Pyramide, die in der Implementation vollkommen ohne Verwendung von JavaScript auskommt.
Abbildung 1: Frei im Raum drehende quadratische Pyramide, rein in CSS3 definiert. Das Beispiel wird momentan (Stand: 10. 12. 2012) nur in Chrome/Safari und Firefox richtig dargestellt.


Abbildung 2: Hintergrund-Grafiken für die Seiten- und Bodenflächen.
Wie funktioniert dies genau? Das untenstehende Listing verrät: Die Pyramide besteht zunächst einmal aus fünf
<div>-Elementen - vier für die Seitenflächen, eines für die Grundfläche - mit den Hintergrundgrafiken in Abbildung 2, die sich gemeinsam im Container mit der ID
pyramid befinden.
pyramid wiederum wird von einem Wrapper-
<div> der ID
camera umgeben. Das eigentliche Markup ist also ausgesprochen winzig, die Hauptarbeit findet in CSS statt.
Die
camera-Stildefinition dient dazu, mittels
perspective und
perspective-origin die Tiefe des perspektivischen Raums sowie den Fluchtpunkt (hier: 50% der Breite und 200 Pixel von oben) festzulegen; in der
pyramid-Definition stehen wichtige Angaben wie die Abmessungen des
<div>, weiterhin ein
position:relative zwecks Reset des Positionierungskontextes,
transform-style: preserve-3d für die Erweiterung des 3D-Kontextes und schließlich die Bindung an den Animationsselektor
turnaround, der die Pyramide automatisch in Endlosschleife um ihre eigene Achse dreht.
Die Flächen der Pyramide gehören sämtlich der Klasse
pyram an, die die Elemente absolut innerhalb des
pyramid-
<div> anordnet; weiterhin hat jede einzelne Fläche mit
one,
two,
three,
four und
base noch eigene Klassendefinitionen - hier finden die eigentlichen Rotationen und Verschiebungen (
rotateX,
rotateY,
rotateZ bzw.
translateX,
translateY,
translateZ um die drei Raumachsen statt, aus deren Kombination sich die Pyramide erst ergibt (Größenänderungen per
scale werden hier nicht benötigt). Die zugehörige Stilangabe ist unschwer erkennbar
transform (siehe für eine genaue Syntaxdefinition:
http://www.w3schools.com/cssref/css3_pr_transform.asp). Die so für ein Element definierten Transformationen bauen übrigens kumulativ aufeinander auf und beziehen sich nicht auf die Achsen im umgebenden kartesischen Raum, sondern auf die Achsen im Element; es macht also beispielsweise durchaus einen Unterschied, in welcher Reihenfolge um welche Achsen rotiert wird!
Die Pyramide wurde in diesem Beispiel übrigens gewählt, um zu demonstrieren, dass mit dieser Herangehensweise - speziell dem kreativen Einsatz von Hintergrundgrafiken - im Prinzip beliebige geometrische Körper konstruiert werden können, auch solche, die nicht sämtlich durch rechteckige bzw. quadratische Flächen begrenzt werden wie etwa der Würfel im
Artikel von Paul Hayes (http://www.paulrhayes.com/2009-07/animated-css3-cube-interface-using-3d-transforms), der zu dieser Weiterentwicklung inspiriert hat.
001: 002: 003: 004: 005: 006: 007: 008: 009: 010: 011: 012: 013: 014: 015: 016: 017: 018: 019: 020: 021: 022: 023: 024: 025: 026: 027: 028: 029: 030: 031: 032: 033: 034: 035: 036: 037: 038: 039: 040: 041: 042: 043: 044: 045: 046: 047: 048: 049: 050: 051: 052: 053: 054: 055: 056: 057: 058: 059: 060: 061: 062: 063: 064: 065: 066: 067: 068: 069: 070: 071: 072: 073: 074: 075: 076: 077: 078: 079: 080: 081: 082: 083: 084: 085: 086: 087: 088: 089: 090: 091: 092: 093: 094: 095: 096: 097: 098: 099: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114:
| <html>
<head>
<style type="text/css">
body { background:#5060ff; }
#camera {
-moz-perspective: 800;
-moz-perspective-origin: 50% 200px;
-webkit-perspective: 800;
-webkit-perspective-origin: 50% 200px;
perspective: 800;
perspective-origin: 50% 200px;
}
#pyramid {
position: relative;
margin:150px auto;
height: 300px;
width: 300px;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-webkit-animation: turnaround 30s linear infinite;
-moz-animation: turnaround 30s linear infinite;
}
@-webkit-keyframes turnaround {
0% { -webkit-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg); }
25% { -webkit-transform:rotateX(90deg) rotateY(90deg) rotateZ(90deg); }
50% { -webkit-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg); }
75% { -webkit-transform:rotateX(270deg) rotateY(270deg) rotateZ(270deg); }
100% { -webkit-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg); }
}
@-moz-keyframes turnaround {
0% { -moz-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg); }
25% { -moz-transform:rotateX(90deg) rotateY(90deg) rotateZ(90deg); }
50% { -moz-transform:rotateX(180deg) rotateY(180deg) rotateZ(180deg); }
75% { -moz-transform:rotateX(270deg) rotateY(270deg) rotateZ(270deg); }
100% { -moz-transform:rotateX(0deg) rotateY(0deg) rotateZ(0deg); }
}
.pyram { width:300px;height:300px;position:absolute; }
.one {
background:url('./p-side.png');
-webkit-transform: rotateX(-30deg) rotateY(180deg) translateY(55px) translateZ(55px) ;
-moz-transform: rotateX(-30deg) rotateY(180deg) translateY(55px) translateZ(55px) ;
}
.two {
background:url('./p-side.png');
-webkit-transform: rotateX(30deg) rotateY(0deg) translateY(55px) translateZ(55px) ;
-moz-transform: rotateX(30deg) rotateY(0deg) translateY(55px) translateZ(55px) ;
}
.three {
background:url('./p-side.png');
-webkit-transform: rotateX(0deg) rotateY(90deg) rotateX(30deg) translateY(55px) translateZ(55px) ;
-moz-transform: rotateX(0deg) rotateY(90deg) rotateX(30deg) translateY(55px) translateZ(55px) ;
}
.four {
background:url('./p-side.png');
-webkit-transform: rotateX(0deg) rotateY(-90deg) rotateX(30deg) translateY(55px) translateZ(55px) ;
-moz-transform: rotateX(0deg) rotateY(-90deg) rotateX(30deg) translateY(55px) translateZ(55px) ;
}
.base {
background:url('./p-base.png');
-webkit-transform: rotateX(-90deg) translateZ(150px);
-moz-transform: rotateX(-90deg) translateZ(150px);
}
</style>
</head>
<body>
<div id="camera">
<div id="pyramid">
<div class="pyram base"></div>
<div class="pyram one"></div>
<div class="pyram two"></div>
<div class="pyram three"></div>
<div class="pyram four"></div>
</div>
</div>
</body>
</html>
|