Wenn du dich für die Welt des 3D-Designs und der Animationen interessierst, bist du hier genau richtig. In dieser Erklärung werde ich dir zeigen, wie du mit der JavaScript-Bibliothek three.js 3D-Welten erstellen und animieren kannst.
Zuallererst: Was ist die Web Graphics Library (WebGL)? Mit dieser Technologie kann man interaktive 2D und 3D Grafiken direkt im Browser anzeigen. Und das ohne eine zusätzliche Software.
Der Funktionsumfang kommt aber mit einem Preis: Die Menge an Code und Hintergrundwissen, die man benötigt, um einfache Szenen zu erstellen, ist ziemlich groß.
Ein Framework wie three.js erleichtert die ganzen Grundlagen und bietet viele vorgefertigte Funktion, Formen, Kameras etc. Außerdem essenziell: Es gibt eine große Community mit Fragen, Antworten und Anleitungen, die dir immer weiterhelfen können.
Three.js ist eine JavaScript-Bibliothek, mit der du 3D-Grafiken direkt im Webbrowser anzeigen kannst. Außerdem ist es Open-Source. Stell dir die gesamte 3D-Welt einfach wie ein Filmset vor: „Licht, Kamera, Action!“. Was benötigt man für ein Filmset? Eine Szene, Schauspieler, Licht und eine Kamera. Und genau das werden wir auch in three.js erstellen, nur dass unser Schauspieler erst mal ein einfacher Würfel ist.
Mit three.js und WebGL können Entwickler komplexe visuelle Effekte erzeugen, interaktive Animationen erstellen und virtuelle Realitäten schaffen.
Zum Beispiel:
Bevor wir beginnen können, müssen wir three.js in unser Projekt einbinden. Dazu können wir entweder die three.js-Dateien herunterladen oder über einen CDN-Link einbinden. Die detaillierte Anleitung zur Installation findest du auf der three.js-Website
Sobald du die Dateien in deine HTML-Datei eingebunden hast, können wir mit dem ersten Projekt starten.
Beginnen wir also mit unserem Filmset und bauen eine Szene.
Die Grundlage einer jeden 3D-Szene in three.js ist die Scene
-Klasse. Diese Scene
-Klasse repräsentiert die 3D-Welt, in der sich unsere Objekte befinden werden. Um eine Scene
-Instanz zu erstellen, müssen wir einfach den folgenden Code ausführen:
const scene = new THREE.Scene();
Dies erstellt eine leere Szene, die wir nun mit Objekten füllen können.
Damit überhaupt was zu sehen ist, brauchen wir eine Kamera. Das ist der Blickwinkel, aus dem wir die ganze Szene betrachten. In three.js können wir verschiedene Kameratypen verwenden, darunter die PerspectiveCamera
und die OrthographicCamera
. Um eine PerspectiveCamera
zu erstellen, füge den Code ein:
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
Hier legen wir das Sichtfeld auf 75 Grad fest, und die near
- und far
-Ebenen auf 0,1 und 1000. Diese Werte bestimmen, welche Objekte innerhalb des Kamera-Sichtfelds gerendert werden und welche nicht. Außerdem verschieben wir die Kamera in Z-Richtung nach oben, damit wir auf das Objekt schauen können.
Um unsere Szene zu rendern, benötigen wir einen Renderer. Der Renderer zeichnet die Szene auf den Bildschirm. In three.js gibt es verschiedene Typen, darunter den WebGLRenderer
, der auf WebGL basiert. Um einen solchen zu erstellen, müssen wir den folgenden Code ausführen:
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
Hier legen wir die Größe des Renderers auf die Größe des Browserfensters fest und fügen das Renderer-Element unserem HTML-Dokument hinzu. Hierfür wird im Hintergrund ein Canvas Element erzeugt. Also eine Leinwand auf der das Bild der 3D-Szene gezeichnet wird.
Jetzt können wir der Szene Objekte hinzufügen. Three.js verfügt über viele integrierte geometrische Formen wie Würfel, Kugeln, Zylinder usw. Man kann auch eigene Modelle und Texturen erstellen und verwenden. Um unter anderem einen Würfel hinzuzufügen, können wir den folgenden Code ausführen:
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// Try to render:
// renderer.render(scene, camera);
Hier erstellt man eine Würfelgeometrie, eine Materialtextur und ein Mesh, das die Geometrie und das Material miteinander verbindet. Dann fügen wir den Würfel der Szene hinzu.
Wenn man an dieser Stelle renderer.render()
ausführt, sieht man noch nichts. Einfach nur ein schwarzer Bildschirm. Wie oben beschrieben benötigen wir in einer Szene auch immer ein Licht, denn ansonsten sieht die Kamera nichts. Ein HemisphereLight
beleuchtet die obere Hemisphäre der 3D gleichmäßig. Der erste Wert ist die Farbe des „Himmels“, die zweite die des „Bodens“. Der dritte Wert ist die Stärke der Beleuchtung.
const light = new THREE.HemisphereLight(0xffffff, 0x080820, 1);
scene.add(light);
// Try to render:
// renderer.render(scene, camera);
Jetzt sollte man die Szene mit dem Würfel endlich sehen. Als Nächstes beschäftigen wir uns mit der Animation.
Nun können wir Szene und Objekte animieren. Three.js bietet verschiedene Animationsmethoden, darunter die requestAnimationFrame
-Methode, um eine kontinuierliche Animation zu erstellen. Um insbesondere den Würfel kontinuierlich rotieren zu lassen, können wir den folgenden Code ausführen:
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
Hier erstellen wir eine Funktion animate()
, die die requestAnimationFrame
-Methode aufruft und den Würfel um 0,01 Grad um die x- und y-Achse dreht. Dann rendern wir die Szene mit dem Renderer.
hier verwendt man die Funktion animate
als callback in requestAnimationFrame
. Diese Animations-Funktion wird also immer wieder aufgerufen und wir starten damit die Uhr der 3D-Welt.
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.querySelector('.example-code').appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00aa00 });
const cube = new THREE.Mesh(geometry, material);
const light = new THREE.HemisphereLight(0xffffff, 0x080820, 1);
scene.add(light);
scene.add(cube);
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
Der drehende Zylinder ist natürlich ein schönes „Hello World“-Beispiel, aber da gibt es noch sehr viel mehr: Das zweite Projekt soll eine 3D-Welle mit mehreren Zylindern darstellen. Wir starten wieder wie zuvor mit der Szene, Kamera und Renderer:
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 50;
camera.position.y = 20;
camera.position.x = 40;
camera.rotation.x = -0.5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
Hier hat sich die Kamera Perspektive und Position verändert. Da wir mehrere Objekte sehen wollen sind die Werte x,y und z weiter vom Zentrum entfernt.
Als Nächstes erstellen wir wieder Geometrie und Material. Dieses Mal nutzen wir eine CylinderGeometry
mit dem Radius 2, Höhe 5 und 30 Segmenten.
Das Material hat jetzt zusätzlich die Eigenschaft wireframe
. Damit wird das Objekt als Gitter dargestellt. Das Licht wird genauso wie zuvor hinzugefügt.
Dann erstellt man ein Array, was mit zehn Zylinder-Objekten gefüllt wird. Wichtig ist, dass die X-Position bei jedem Objekt verschoben wird, damit alle nebeneinander stehen.
const geometry = new THREE.CylinderGeometry(2, 2, 5, 30);
const material = new THREE.MeshBasicMaterial({
color: 0x0099aa,
wireframe: true
});
const light = new THREE.HemisphereLight(0xffffff, 0x080820, 1);
scene.add(light);
let objArray = [];
for (let i = 0; i < 10; ++i) {
const cylinder = new THREE.Mesh(geometry, material);
cylinder.position.x = 8 * i;
scene.add(cylinder);
objArray.push(cylinder);
}
Jetzt kommen wir zum interessanten Teil: Die Zylinder sollen sich wellenförmig vergrößern und verkleinern.
Dafür wird die .scale
Eigenschaft der Objekte benutzt. Die Y-Skalierung wird also mit jedem Render-Durchgang neu berechnet. Die animate
Funktion hat hier einen neuen Parameter. time
beschreibt die aktuelle Zeit in des Render-Durchgangs in Millisekunden.
Es wird also eine Sinus-Funktion in Abhängigkeit der Zeit und der X-Position berechnet. Die beiden Faktoren 0.002 und 0.02 sind so gewählt, dass die Animation schön langsam und flüssig aussieht.
Höhere Werte bei der Zeit lassen die Animation schneller ablaufen. Höhere Werte bei der Position lassen den Unterschied der einzelnen Zylinder größer werden.
function animate(time) {
requestAnimationFrame(animate);
for (let obj of objArray) {
obj.scale.y = 0.5 * Math.sin(0.002 * time + 0.02 * obj.position.x) + 1;
}
renderer.render(scene, camera);
}
animate();
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
50,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 50;
camera.position.y = 20;
camera.position.x = 40;
camera.rotation.x = -0.5;
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.querySelector('.example-code').appendChild(renderer.domElement);
const geometry = new THREE.CylinderGeometry(2, 2, 5, 30);
const material = new THREE.MeshBasicMaterial({
color: 0x0099aa,
wireframe: true
});
const light = new THREE.HemisphereLight(0xffffff, 0x080820, 1);
scene.add(light);
let objArray = [];
for (let i = 0; i < 10; ++i) {
const cylinder = new THREE.Mesh(geometry, material);
cylinder.position.x = 8 * i;
scene.add(cylinder);
objArray.push(cylinder);
}
function animate(time) {
requestAnimationFrame(animate);
for (let obj of objArray) {
obj.scale.y = 0.5 * Math.sin(0.002 * time + 0.02 * obj.position.x) + 1;
}
renderer.render(scene, camera);
}
animate();
Das war ein kurzer Einblick in die Grundlagen von three.js mit Javascript. Wenn du die beiden Projekte erfolgreich implementiert hast, kannst du kreativ werden.
Die Codebeispiele können gut als Basis zum Ausprobieren benutzt werden: Parameter verändern, Geometrien austauschen, Animation zufällig anstatt mit einer Welle usw. Oder man ersetzt die Animationen durch Physik. Mit Physik-Engines wie Cannon.js kann man realistische Animation mit Gravitation, Kollision usw. erstellen.
Zum Abschluss noch ein kurzes Fazit: