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: