Mit den folgenden Schritten kann man eine webgl three.js Komponenete in Angular erstellen:
- Installiere Three.js als Abhängigkeit:
npm install three
2. Installiere die Three.js-Typdefinitionen, um die Typüberprüfung und Code-Intelligenz in deinem Angular-Projekt zu verbessern. Führe den folgenden Befehl aus:
npm install @types/three --save-dev
3. Erstelle einer Angular Komponente
import {Component, OnInit} from '@angular/core';
import * as THREE from 'three';
import {OrbitControls} from "three/examples/jsm/controls/OrbitControls";
import {TextGeometry} from "three/examples/jsm/geometries/TextGeometry";
import {FontLoader} from "three/examples/jsm/loaders/FontLoader";
import {Mesh, MeshBasicMaterial, Scene, SphereGeometry, WebGLRenderer} from "three";
@Component({
selector: 'app-mindmap',
template: `
<div id="mindmap" #mindmap></div>
`,
styles: [
'#mindmap{ width: 1200px;height: 400px;display: block;}'
]
})
export class MindmapComponent implements OnInit {
nodeA!: Mesh<SphereGeometry, MeshBasicMaterial>;
nodeB!: Mesh<SphereGeometry, MeshBasicMaterial>;
nodeC!: Mesh<SphereGeometry, MeshBasicMaterial>;
@ViewChild('mindmap', { static: true }) mindmap?: ElementRef;
private font: any;
width = 1200;
height = 400;
private renderer!: WebGLRenderer;
private scene!: Scene;
ngOnInit(): void {
// Laden der Schriftart
var fontLoader = new FontLoader();
fontLoader.load('assets/font/helvetiker_regular.typeface.json', (font: any) => {
this.font = font;
this.drawMindmap();
});
}
private drawMindmap()
{
// Initialisieren der Szene, Kamera und Renderer
this.initialize();
this.createNodes();
// Erstellen der Textgeometrie mit der geladenen Schriftart
this.createText();
this.addControls();
this.createConnections();
}
private initialize() {
this.scene = new THREE.Scene();
this.renderer = new THREE.WebGLRenderer({antialias: true});
this.renderer.setSize(this.width, this.height);
this.renderer.setClearColor(0xffffff); // Hintergrundfarbe auf Weiß setzen
this.mindmap?.nativeElement.appendChild(this.renderer.domElement);
const axesHelper = new THREE.AxesHelper( 1 );
this.scene.add( axesHelper );
}
private createNodes() {
// Erstellen der Knoten-Geometrie und Materialien
var geometry = new THREE.SphereGeometry(0.05, 32, 32); // Größe der Kugeln auf 10% reduzieren
var material = new THREE.MeshBasicMaterial({color: 0x0000ff}); // Dunkelblau für das Material
// Erstellen der Knoten A
var nodeA = new THREE.Mesh(geometry, material);
this.scene.add(nodeA);
nodeA.position.set(-1, 0, 0);
this.nodeA = nodeA;
// Erstellen der Knoten B
var nodeB = new THREE.Mesh(geometry, material);
this.scene.add(nodeB);
nodeB.position.set(0, 1, 0); // Knoten B nach unten verschieben
this.nodeB = nodeB;
// Erstellen der Knoten C
var nodeC = new THREE.Mesh(geometry, material);
this.scene.add(nodeC);
nodeC.position.set(1, 0, 0);
this.nodeC= nodeC;
}
private addControls() {
/**
* fov: Das Sichtfeld (Field of View) in Grad. Es definiert den vertikalen Erfassungswinkel der Kamera. Ein größerer Wert führt zu einem breiteren Sichtfeld und umgekehrt.
* aspect: Das Seitenverhältnis (Aspect Ratio) der Kamera. Es wird üblicherweise als Breite durch Höhe definiert. In diesem Fall wird this.width / this.height verwendet, wobei this.width und this.height die Breite und Höhe des Anzeigebereichs (Canvas oder Fenster) sind. Das Seitenverhältnis beeinflusst das Verhältnis der horizontalen zur vertikalen Sicht und wird verwendet, um die Szene korrekt zu skalieren.
* near: Der nahe Clip-Abstand. Objekte, die näher an der Kamera liegen als dieser Wert, werden abgeschnitten und nicht gerendert.
* far: Der ferne Clip-Abstand. Objekte, die weiter entfernt von der Kamera liegen als dieser Wert, werden ebenfalls abgeschnitten.
*/
var camera = new THREE.PerspectiveCamera(75, this.width / this.height, 0.1, 1000);
// Berechnen der Bounding Box der Knoten
const boundingBox = new THREE.Box3().setFromObject(this.nodeA);
boundingBox.expandByObject(this.nodeB);
boundingBox.expandByObject(this.nodeC);
const center = new THREE.Vector3();
const size = new THREE.Vector3();
boundingBox.getCenter(center);
boundingBox.getSize(size);
// Berechnen des Kameraabstands basierend auf der Größe der Bounding Box
const maxDimension = Math.max(size.x, size.y, size.z);
const cameraDistance = maxDimension ; // Faktor 2 für etwas zusätzlichen Abstand
camera.position.z = cameraDistance;
// Setzen der Kamera-Position auf den Schwerpunkt der Bounding Box
camera.lookAt(center);
// Anpassen des Kamera-Zooms
const cameraZoom = 1.5; // Passen Sie den Zoomwert an Ihre Anforderungen an
camera.zoom = cameraZoom;
camera.updateProjectionMatrix();
// Maussteuerung für das Drehen der Szene hinzufügen
var controls = new OrbitControls(camera, this.renderer.domElement);
controls.target.set(0, 0, 0); // Drehachse in der Mitte des Bildes
// Animations-Schleife
const animate = () => {
requestAnimationFrame(animate);
// Animationen oder Interaktionen hier einfügen
this.renderer.render(this.scene, camera);
}
animate();
}
private createText() {
var textMaterial = new THREE.MeshBasicMaterial({color: 0x000000}); // Schriftfarbe auf Schwarz setzen
var textGeometryA = new TextGeometry("A", {
font: this.font,
size: 0.05, // Größe der Schrift auf 5% reduzieren
height: 0.005, // Höhe der Schrift auf 0.5% reduzieren
});
var textA = new THREE.Mesh(textGeometryA, textMaterial);
textA.position.copy(this.nodeA.position);
textA.position.y -= 0.2; // Knoten A TextNode nach unten verschieben
this.scene.add(textA);
var textGeometryB = new TextGeometry("B", {
font: this.font,
size: 0.05,
height: 0.005,
});
var textB = new THREE.Mesh(textGeometryB, textMaterial);
textB.position.copy(this.nodeB.position);
textB.position.y -= 0.2; // Knoten B TextNode nach unten verschieben
this.scene.add(textB);
var textGeometryC = new TextGeometry("C", {
font: this.font,
size: 0.05,
height: 0.005,
});
var textC = new THREE.Mesh(textGeometryC, textMaterial);
textC.position.copy(this.nodeC.position);
textC.position.y -= 0.2; // Knoten C TextNode nach unten verschieben
this.scene.add(textC);
}
private createConnections() {
// Erstellen der Beziehungslinien
var lineMaterial = new THREE.LineBasicMaterial({color: 0x000000, linewidth: 4}); // Linienfarbe auf Schwarz und Linienbreite auf 4 setzen
var lineABGeometry = new THREE.BufferGeometry().setFromPoints([this.nodeA.position, this.nodeB.position]);
var lineAB = new THREE.Line(lineABGeometry, lineMaterial);
this.scene.add(lineAB);
var lineBCGeometry = new THREE.BufferGeometry().setFromPoints([this.nodeB.position, this.nodeC.position]);
var lineBC = new THREE.Line(lineBCGeometry, lineMaterial);
this.scene.add(lineBC);
var lineCAGeometry = new THREE.BufferGeometry().setFromPoints([this.nodeC.position, this.nodeA.position]);
var lineCA = new THREE.Line(lineCAGeometry, lineMaterial);
this.scene.add(lineCA);
}
}
Ergebnis:


