Angular: Webcam ansteuern

Angular: Webcam ansteuern
09/2026
Noel H. | Solution Engineer

TL;DR

Wie lassen sich beschädigte Waren direkt im Browser fotografieren, ohne zusätzliche Software? Der Beitrag zeigt eine praxisnahe Lösung mit Angular, Node.js und der Browser-Schnittstelle getUserMedia. Behandelt werden der Aufbau einer sauberen Navigation, die Implementierung einer Kamerakomponente zur Bildaufnahme sowie die korrekte Freigabe der Kamera über die ngOnDestroy-Methode. Das Szenario ist besonders relevant für Retourenmanagement, Schadenserfassung und Qualitätssicherung.

Ein Kunde äußerte den Wunsch, beschädigte Waren direkt über eine im Browser integrierte Webcam und ohne den Einsatz zusätzlicher Software fotografieren zu können. Dieses Szenario ist in zahlreichen geschäftlichen Kontexten von hoher Relevanz, beispielsweise im Bereich des Retourenmanagements, der Schadenserfassung oder der Qualitätssicherung.

Im vorliegenden Blog-Artikel wird eine exemplarische Lösung für dieses Anwendungsbeispiel vorgestellt. Mithilfe von Angular, Node.js und Visual Studio Code wird eine Webanwendung entwickelt, die es ermöglicht, über die Kamera des Endgeräts Bilder aufzunehmen und unmittelbar im Frontend anzuzeigen.

‍

Implementierung

‍

Vorbereitungen

Bevor die Implementierung beginnt, wird eine passende Entwicklungsumgebung benötigt. Dafür müssen folgende Dinge gegeben sein:

  • Node.js
  • Angular CLI (mindestens Version 14)
  • Visual Studio Code

‍

App anlegen

Um die Anwendung zu erstellen, können über das Terminal die folgenden Befehle ausgeführt werden:

ng new angular-example-app --style=scss 

cd angular-example-app 

code .

‍

Serverseitiges Rendering muss bei der Erstellung der App nicht ausgewählt werden.

Die Anwendung kann über den Befehl ng serve lokal gestartet und mit Strg + c gestoppt werden.

‍

Komponenten anlegen

Um Angular-Komponenten anzulegen, werden die folgenden Befehle ausgeführt:

ng generate component navigation-bar --standalone 

ng generate component image-manager

‍

Navigationskomponente implementieren

Für eine saubere Implementierung wird zuerst eine Navigation angelegt, über die im Anschluss zur Kamerakomponente navigiert werden kann.

‍

HTML implementieren

Hierfür reicht eine Nav mit mehreren ul-Elementen:

<nav class="navbar"> 
    <ul> 
      <li><a (click)="navigateTo('/')">Home</a></li> 
      <li><a (click)="navigateTo('/manager')">Image-Manager</a></li>       
    </ul> 
  </nav> 

‍

Der Nav wird eine navbar-Klasse gegeben, die anschließend im SCSS angepasst wird.

‍

SCSS implementieren

Für die Navbar soll sichergestellt werden, dass sie beim Scrollen oben bleibt und vor anderen Elementen angezeigt wird, die sich auf der gleichen Ebene befinden können.

.navbar { 
    background-color: #333; /* Dunkler Balken */ 
    padding: 1em; /* Abstand für den Text */ 
    width: 100%; /* Breite auf die gesamte Seite strecken */ 
    position: fixed; /* Navbar bleibt oben, auch beim Scrollen */ 
    top: 0; /* Ganz oben auf der Seite */ 
    left: 0; /* Links ausgerichtet */ 
    z-index: 1000; /* Navbar bleibt über anderen Elementen */ 
  } 

‍

Die Elemente in der Liste wirken übersichtlicher, wenn sie ohne Punkte angezeigt werden.

.navbar ul { 
    list-style-type: none; /* Keine Punkte vor den Listenelementen */ 
    margin: 0; 
    padding: 0; 
    display: flex; /* Elemente nebeneinander */ 
    justify-content: center; /* Zentriere die Navigation in der Mitte des Balkens */ 
  } 

‍

Danach wird ein Abstand zwischen den Links eingefügt:

.navbar li {
    margin-right: 1.5em; /* Abstand zwischen den Links */ 
  }

‍

Damit der Text leichter erkennbar ist, wird er weiß dargestellt und in seiner Größe angepasst:

.navbar a { 
    color: white; /* Weißer Text */ 
    text-decoration: none; /* Keine Unterstreichung */ 
    font-size: 1.2em; /* Etwas größere Schrift */ 
    padding: 0.5em; 
  }

‍

Um erkenntlich zu machen, dass die Maus einen Link auswählt, wird ein Hover-Effekt hinzugefügt:

 .navbar a:hover { 
    text-decoration: underline; /* Unterstreiche den Link beim Hover */ 
    cursor:pointer; 
  } 

‍

TypeScript implementieren

Anschließend wird eine Methode zur Navigation hinzugefügt:

1import { Component } from '@angular/core'; 
2import { NavigationEnd, Router } from '@angular/router'; 
3
4@Component({ 
5  selector: 'app-navigation-bar', 
6  standalone: true, 
7  imports: [], 
8  templateUrl: './navigation-bar.component.html', 
9  styleUrl: './navigation-bar.component.scss' 
10}) 
11 
12
13export class NavigationBarComponent { 
14  constructor(private router: Router) {   
15
16  } 
17
18  public navigateTo(route: string): void { 
19    let self = this; 
20    self.router.navigate([route]);  // Programmatic navigation 
21
22  } 
23} 

‍

Kamerakomponente implementieren

HTML implementieren

Für das HTML wird ein Container erstellt, der auf der einen Seite die Kamera durch ein videoElement und das Bild durch ein canvasElement darstellt und auf der anderen Seite eine Liste der aufgenommenen Bilder anzeigt.

1<div class="container"> 
2    <div class="webcam-container"> 
3      <button (click)="startWebcam()">Open Webcam</button> 
4   
5      <video #videoElement width="320" height="240" autoplay></video> 
6      <canvas #canvasElement width="320" height="240"></canvas> 
7   
8      <!-- Button to capture an image --> 
9      <button (click)="takeImage()">Take Image</button> 
10    </div> 
11
12    <!-- New container for displaying captured images --> 
13
14    <div class="image-list-container"> 
15      <h3>Captured Images</h3> 
16      <div *ngIf="capturedImages.length === 0">No images captured yet.</div> 
17      <div class="image-list"> 
18        <img *ngFor="let img of capturedImages" [src]="img" class="captured-image"/> 
19      </div> 
20    </div> 
21  </div> 

‍

SCSS implementieren

Damit die Elemente geordneter aussehen, wird eine SCSS-Datei hinzugefügt.

1.container { 
2    margin-top:80px; 
3    display: flex; 
4    flex-direction: row; 
5    justify-content: space-between; 
6    align-items: flex-start; 
7  } 
8
9  .webcam-container { 
10    display: flex; 
11    flex-direction: column; 
12    align-items: center; 
13    margin-right: 20px; 
14  } 
15
16  video, canvas { 
17    border: 2px solid #333; 
18    margin: 10px; 
19  } 
20  
21  button { 
22    margin-bottom: 10px; 
23    padding: 10px 20px; 
24    font-size: 16px; 
25    cursor: pointer; 
26  } 
27  
28  .image-list-container { 
29    display: flex; 
30    flex-direction: column; 
31    align-items: center; 
32    width: 300px; 
33  } 
34
35  .image-list { 
36    display: flex; 
37    flex-direction: column; 
38    align-items: center; 
39    width: 100%; 
40  }   
41
42  .captured-image { 
43    width: 100%; 
44    height: auto; 
45    border: 1px solid #333; 
46    margin: 10px 0; 
47  } 

‍

TypeScript implementieren

In der TypeScript-Datei wird eine Methode erstellt, um die Kamera zu starten. Durch navigator.mediaDevices.getUserMedia() wird die Berechtigung für die Webcam angefragt, um sie danach zu verwenden.

In der takeImage()-Methode wird das aktuelle Bild der Kamera aufgenommen und anschließend der Liste mit Bildern hinzugefügt.

Die ngOnDestroy()-Methode wird ausgeführt, wenn die Komponente nicht mehr gebraucht (zerstört) wird, z. B. wenn der Tab mit der Kamerakomponente geschlossen wird. Dort wird sichergestellt, dass die Kamera beendet wird, da sie nicht mehr benötigt wird.

1import { Component, ViewChild, ElementRef, OnDestroy } from '@angular/core'; 
2import { CommonModule } from '@angular/common'; 
3
4@Component({ 
5  selector: 'app-image-manager', 
6  standalone: true, 
7  imports: [CommonModule], 
8  templateUrl: './image-manager.component.html', 
9  styleUrl: './image-manager.component.scss' 
10}) 
11
12export class ImageManagerComponent  implements OnDestroy{ 
13 
14  @ViewChild('videoElement') videoElement!: ElementRef<HTMLVideoElement>; 
15  @ViewChild('canvasElement') canvasElement!: ElementRef<HTMLCanvasElement>; 
16
17  stream: MediaStream | null = null; 
18  capturedImages: string[] = [];  // Array to store captured image URLs 
19
20
21startWebcam(): void { 
22    if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { 
23      navigator.mediaDevices.getUserMedia({ video: true }) 
24        .then((stream) => { 
25          this.stream = stream; 
26          this.videoElement.nativeElement.srcObject = stream; 
27        }) 
28
29        .catch((error) => { 
30          console.error('Error accessing the webcam:', error); 
31        }); 
32
33    } else { 
34      alert('Webcam not supported in this browser.'); 
35    } 
36  } 
37
38  takeImage(): void { 
39    const canvas = this.canvasElement.nativeElement; 
40    const video = this.videoElement.nativeElement; 
41    const context = canvas.getContext('2d');
42
43    if (context) { 
44      context.drawImage(video, 0, 0, canvas.width, canvas.height); 
45      const imageUrl = canvas.toDataURL('image/png'); 
46      this.capturedImages.push(imageUrl); 
47    } 
48  } 
49
50  ngOnDestroy(): void { 
51    if (this.stream) { 
52      this.stream.getTracks().forEach(track => track.stop()); 
53    } 
54  } 
55} 

‍

Navigation anpassen

Damit die Kamerakomponente aufgerufen werden kann und die Navigation funktioniert, muss die AppComponent angepasst werden.

‍

AppComponent-HTML anpassen

Hier wird das aktuelle HTML gegen Folgendes ausgetauscht:

<app-navigation-bar></app-navigation-bar>  

<router-outlet></router-outlet>

‍

AppComponent-TypeScript anpassen

Hier werden Referenzen zu den benötigten Komponenten hinzugefügt:

import { NavigationEnd, Router, RouterOutlet } from '@angular/router'; 

import { NavigationBarComponent } from './navigation-bar/navigation-bar.component'; 

‍

Danach muss Folgendes im Konstruktor stehen:

1constructor(private router: Router) { 
2      this.router.events.subscribe(event => { 
3        if (event instanceof NavigationEnd) { 
4          console.log('Navigated to:', event.urlAfterRedirects); 
5        } 
6      }); 
7  } 

‍

App-Routes anpassen

In app.routes.ts werden nun die Routen konfiguriert:

1import { Routes } from '@angular/router'; 
2import { AppComponent } from './app.component'; 
3import { ImageManagerComponent } from './image-manager/image-manager.component';  
4export const routes: Routes = [ 
5    {path:'', component: AppComponent},    
6    {path:'manager', component: ImageManagerComponent}     
7]; 

‍

Alternativ kann eine Home-Komponente erstellt werden, die als Startseite aufgerufen und anstelle der AppComponent eingebunden wird. Die vorgestellte Konfiguration ist jedoch ebenfalls funktionsfähig.

Aufgenommene bilder mit angesteuerter Webcam.
Noel H. | Solution Engineer
Noel H. | Solution Engineer

Entwickler-Schulung

Diese Beiträge entstehen aus der täglichen Arbeit unserer Entwicklerinnen und Entwickler. Devware gibt dieses Wissen auf Anfrage auch als Schulung weiter, zu .NET, Blazor und anderen Sprachen.
Pfeil-Icon – Mehr erfahren

Mehr zum Thema

Pfeil nach rechts (Verlinkung)
Unittests in C#
09/2026

Unittests in C#

Blauer Pfeil nach rechts (Verlinkung)
MCP-Server in C# bauen
09/2026

MCP-Server in C# bauen

Blauer Pfeil nach rechts (Verlinkung)
Mirror-Shape-Pattern für Blazor EditForm
09/2026

Mirror-Shape-Pattern für Blazor EditForm

Blauer Pfeil nach rechts (Verlinkung)
Kundendaten in KI-Systeme geben: wann es erlaubt ist und wie Sie es bauen
09/2026

Kundendaten in KI-Systeme geben: wann es erlaubt ist und wie Sie es bauen

Blauer Pfeil nach rechts (Verlinkung)