import { Component, ElementRef, HostListener, inject, ViewChild } from '@angular/core'; import { ThemeSwitchService } from '../../service/theme-switch.service'; @Component({ selector: 'app-background', imports: [], templateUrl: './background.html', styleUrl: './background.scss' }) export class Background { private themeSwitchService = inject(ThemeSwitchService); constructor() {} @ViewChild('canvas', { static: true }) canvasRef!: ElementRef; // Config private numStars = 150; private minBlink = 0.2; private maxBlink = 1; private blinkSpeed = 0.002; // Stern blinkt langsamer oder schneller private maxSpeed = 0.1; // Sternbewegungsgeschwindigkeit private parallaxFactor = 0.5; // Scroll-Parallax-Faktor // Feature toggles private enableBlink = true; private enableMovement = true; private ctx!: CanvasRenderingContext2D; private stars: Star[] = []; private width = window.innerWidth; private height = window.innerHeight; private animationId!: number; private scrollY = window.scrollY; ngOnInit() { const canvas = this.canvasRef.nativeElement; this.ctx = canvas.getContext('2d')!; canvas.width = this.width; canvas.height = this.height; for (let i = 0; i < (this.numStars) * (document.body.scrollHeight / this.height); i++) { this.stars.push({ x: Math.random() * this.width, y: Math.random() * document.body.scrollHeight, radius: Math.random() * 1.5 + 0.5, alpha: this.minBlink + Math.random() * (this.maxBlink - this.minBlink), alphaChange: (Math.random() * this.blinkSpeed) + 0.0005, vx: (Math.random() - 0.5) * this.maxSpeed, vy: (Math.random() - 0.5) * this.maxSpeed }); } this.animate(); } @HostListener('window:resize') onResize() { this.width = window.innerWidth; this.height = window.innerHeight; const canvas = this.canvasRef.nativeElement; canvas.width = this.width; canvas.height = this.height; } @HostListener('window:scroll') onScroll() { this.scrollY = window.scrollY; } private animate() { const ctx = this.ctx; ctx.clearRect(0, 0, this.width, this.height); for (let star of this.stars) { // Blinken if (this.enableBlink) { star.alpha += star.alphaChange; if (star.alpha > this.maxBlink || star.alpha < this.minBlink) star.alphaChange *= -1; } // Bewegung if (this.enableMovement) { star.x += star.vx; star.y += star.vy; } // Bildschirm-Ränder if (star.x < 0) star.x = this.width; if (star.x > this.width) star.x = 0; if (star.y < 0) star.y = document.body.scrollHeight; if (star.y > document.body.scrollHeight) star.y = 0; // Stern zeichnen mit Scroll-Parallax ctx.beginPath(); ctx.arc(star.x, star.y - this.scrollY * this.parallaxFactor, star.radius, 0, Math.PI * 2); ctx.fillStyle = this.themeSwitchService.darkMode() ? `rgba(255, 215, 0, ${star.alpha})` : `rgba(184, 134, 11, ${star.alpha})`; ctx.fill(); } this.animationId = requestAnimationFrame(() => this.animate()); } ngOnDestroy() { cancelAnimationFrame(this.animationId); } } interface Star { x: number; y: number; radius: number; alpha: number; alphaChange: number; vx: number; vy: number; }