Integration Basics: Integrating BabylonJS 3D Engine Into An Angular Business Application – Part 1

In this two parts article, I will demonstrate how easy it can be to integrate a 3D engine like BabylonJS into a business application built with a SPA framework like Angular. You will see how those two frameworks can interact with each other and where possible performance pitfalls may occur.

In diesem Artikel:

Integration Basics: Integrating BabylonJS 3D Engine Into An Angular Business Application – Part 1
Max Schulte ist Consultant bei Thinktecture mit dem Schwerpunkt auf Angular und 2D/3D Visualisierung.

What to expect in part 1

This part is about the integration basics of BabylonJS and Angular. I will show you how you can use your existing knowledge of Angular and combine it with a graphics engine to create a compelling and modern user experience. You can find the performance-related aspects in part 2.

Integration Demo, BabylonJS and Angular working together

Take a look at the demo below, this is what we will discuss here. More specific, I will demonstrate how to implement the first tab (unoptimized), the other versions are discussed in part 2.

A Primer on BabylonJS

BabylonJS is a 2D/3D engine for the web and is based on the WebGL standard. It is possible to create complex visualizations, configurator tools, or games that run blazingly fast and are easy to use.

In contrast to other engines like Unity or Unreal, content created with BabylonJS is written in JavaScript or TypeScript. This means that it runs natively in the browser and therefore we can enter, manipulate, and extend the graphic content generation at any time. This is key for an easy integration between any graphics engine and SPA frameworks.

Where to start

Angular is a well-known application framework and you surely know how to use it. However, you might not yet know the intrinsics and basics of BabylonJS. BabylonJS provides us with a number of concepts and API interfaces that we need to integrate with our Angular code. The most important objects in the API are Engine and Scene. A closer look will show that they are similar to Angular services and components, concept-wise.

Before we start, we have to make a few assumptions:

  1. The Engine resembles an Angular service
  2. The Engine renders a Scene
  3. Scene corresponds to an Angular component
  4. Scene holds information about its state

An engine works by rapidly rendering the scene image by image, this is called the renderLoop.

In the next paragraphs, I will demonstrate you my approach to integrate Angular and BabylonJS.

Providing the Engine as an Angular Service

As mentioned, the Engine can be compared to a service. What we have to do is to manage the state and provide it to the engine.

We embed the Engine by using an Angular service as our singleton and proxy to the Engine.

					// store the Engine
engine: Engine;

// the Engine will render into the Canvas element
start(canvas: ElementRef<HTMLCanvasElement>, scene: Scene) {
  this.engine = new Engine(this.canvas, true);

  // ... you can add content to the Scene

  // ignore the change events from the Engine in the Angular ngZone
  this.ngZone.runOutsideAngular( () => {
    // start the render loop and therefore start the Engine
    this.engine.runRenderLoop(() => scene.render())

Create the „engine“ with some content and start the render loop.

The service holds the Engine state, but we also need a way to manipulate the Scene. Each Scene could correspond to an Angular component.

The Scene Component

Using an Angular component, we integrate the Scene perfectly in our existing architecture.

The component template must contain a Canvas and a reference where the graphics will be rendered:

					<div class="wrapper">
    <canvas #rCanvas id="rCanvas"></canvas>

That reference will be selected by our component and is provided to the service.

					// ...
@ViewChild('rCanvas', {static: true})
canvasRef: ElementRef<HTMLCanvasElement>;

private scene: Scene;

constructor(private readonly engineService: EngineService) {}

// ...
ngOnInit(): void {
  // .. manipulate the scene

ngAfterViewInit(): void {
    // start the Engine
    // be aware that we have to setup the Scene before

The scene component calling the created Angular EngineService to start the graphics engine

Notice: To be sure that the Canvas element is available in the DOM, the Engine service is started after the view has been initialized.

But even if we are now able to display things, there are no interactions possible, yet. How can these two separate systems interact?

Interaction between Angular and BabylonJS

Now that everything is set up, we can begin to implement interactions between our graphics framework and the business application framework.

As discussed, the Engine renders the Scene in a loop, and therefore, we can change the Scene, and the Engine will update the rendered image accordingly.

Creating interaction with the scene is as easy as subscribing to any event in Angular, in our case listening to changes of our configuration object. The renderLoop will do the rest by updating the rendered scene on the next iteration.

					this.preferences.config.subscribe(config => {
    // update config
    this.someConfig = config;
    // change / update asteroids

The scene component, listening to configuration changes

The other way round from BabylonJS to Angular is also straightforward: We add an event listener to e.g. the Scene we want to interact with and do something with the event we receive.

					const jupyter = this.engineService.createObject('jupyter');
jupyter.actionManager = new ActionManager(this.engineService.scene);
jupyter.actionManager.registerAction(new ExecuteCodeAction(ActionManager.OnPickUpTrigger,
      () =>;

Creating a Scene object and adding an action to it

The ActionManagerExecuteCodeAction, and OnPickUpTrigger objects are BabylonJS’s way to register an onClicked listener that executes a function. In this case, we will pass on the request and increase a click counter.

As you can see, integrating BabylonJS into Angular is straightforward, interaction is as easy as calling a function.


At this point, we have integrated Angular and BabylonJS. However it is not performant yet. Take a look at the Stackblitz demo and select unoptimized to see the effect of our doing so far.

Wrap Up

That’s it! We successfully integrated the 2D/3D graphics engine BabylonJS in our business application written with Angular and Typescript.

In part 2, you will see where performance pitfalls are, how to find and avoid them. Subscribe to our monthly newsletter to not miss the next article.


Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
Configuring Lazy Loaded Angular Modules

Configuring Lazy Loaded Angular Modules

Making our Angular modules configurable is an important step in building a reusable architecture. Having used Angular for a while you might be familiar with the commonly used forRoot() and forChild() functions, that some modules provide you with. But what is the best way to provide configuration in these cases?
Master Web Component Forms Integration – with Lit and Angular

Master Web Component Forms Integration – with Lit and Angular

When a company has cross-framework teams, it is a good choice to use Web Components to build a unified and framework-independent component library. However, some pitfalls are to consider when integrating these components into web forms. Therefore, for a better understanding, we will look at two possible approaches and try to integrate them into an Angular form as an example.

Notice: All code samples are available on Github!
Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Asynchrone Operationen: Blazor WebAssembly für Angular-Entwickler – Teil 5 [Screencast]

Eine Webanwendung will natürlich auch mit Daten gefüttert werden. Doch diese müssen irgendwo her kommen. Nichts liegt näher als diese von einer Web API zu laden. Dieser Screencast zeigt, wie asynchrone Operationen in Blazor funktionieren und welche gravierenden Unterschiede es zu Angular gibt.
Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

Typings: Blazor WebAssembly für Angular-Entwickler – Teil 4 [Screencast]

C# und TypeScript entstammen der Feder der selben Person. Doch sind sie deshalb auch gleich? In diesem Teil der Screencast-Serie erfahren Sie, wie mit Typen in den beiden Programmiersprachen verfahren wird und welche Unterschiede es gibt.
Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Bindings: Blazor WebAssembly für Angular-Entwickler – Teil 3 [Screencast]

Wer Komponenten einsetzt, steht früher oder später vor der Fragestellung, wie man Daten an die Komponente übergibt oder auf Ereignisse einer Komponente reagiert. In diesem Screencast wird gezeigt wie Bindings bei Komponenten funktionieren, also wie eine Komponente Daten von außerhalb benutzen und Rückmeldung bei Aktionen geben kann.
Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Komponenten: Blazor WebAssembly für Angular-Entwickler – Teil 2 [Screencast]

Bei der Entwicklung einer Webapplikation kommt es ständig vor, dass UI-Teile immer und immer wieder verwendet werden. Damit nicht immer Copy & Paste verwendet werden muss, können diese Teile in Komponenten zusammengefasst werden.